703 lines
22 KiB
C
703 lines
22 KiB
C
#include "ctlspriv.h"
|
|
|
|
|
|
LRESULT WINAPI SendNotifyEx(HWND hwndTo, HWND hwndFrom, int code, NMHDR FAR* pnmhdr, BOOL bUnicode)
|
|
{
|
|
CONTROLINFO ci;
|
|
|
|
if (!hwndTo) {
|
|
if (IsWindow(hwndFrom))
|
|
hwndTo = GetParent(hwndFrom);
|
|
if (!hwndTo)
|
|
return 0;
|
|
}
|
|
|
|
|
|
ci.hwndParent = hwndTo;
|
|
ci.hwnd = hwndFrom;
|
|
ci.bUnicode = bUnicode;
|
|
#if TODO
|
|
ci.uiCodePage = CP_ACP;
|
|
#endif
|
|
|
|
return CCSendNotify(&ci, code, pnmhdr);
|
|
}
|
|
|
|
|
|
LRESULT WINAPI CCSendNotify(CONTROLINFO FAR * pci, int code, LPNMHDR pnmhdr)
|
|
{
|
|
NMHDR nmhdr;
|
|
int id;
|
|
#ifdef UNICODE
|
|
LPVOID pvThunk1 = NULL;
|
|
LPVOID pvThunk2 = NULL;
|
|
DWORD dwThunkSize = 0;
|
|
LRESULT lRet;
|
|
BOOL bSet = FALSE;
|
|
#endif
|
|
|
|
// unlikely but it can technically happen -- avoid the rips
|
|
if (pci->hwndParent == NULL)
|
|
return 0;
|
|
|
|
// If pci->hwnd is -1, then a WM_NOTIFY is being forwared from one control to a parent.
|
|
// EG: Tooltips sent a WM_NOTIFY to toolbar, and toolbar is forwarding it to the real parent window.
|
|
if (pci->hwnd != (HWND) -1) {
|
|
id = pci->hwnd ? GetDlgCtrlID(pci->hwnd) : 0;
|
|
|
|
if (!pnmhdr)
|
|
pnmhdr = &nmhdr;
|
|
|
|
pnmhdr->hwndFrom = pci->hwnd;
|
|
pnmhdr->idFrom = id;
|
|
pnmhdr->code = code;
|
|
} else {
|
|
id = pnmhdr->idFrom;
|
|
code = pnmhdr->code;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
/*
|
|
* All the thunking for Notify Messages happens here
|
|
*/
|
|
if (!pci->bUnicode) {
|
|
switch( code ) {
|
|
case LVN_ODFINDITEMW:
|
|
{
|
|
LV_FINDINFO *plvfi;
|
|
|
|
pnmhdr->code = LVN_ODFINDITEMA;
|
|
|
|
// Hack Alert! This code assumes that all fields of LV_FINDINFOA and
|
|
// LV_FINDINFOW are exactly the same except for the string pointers.
|
|
Assert(sizeof(LV_FINDINFOA) == sizeof(LV_FINDINFOW));
|
|
|
|
// Since WCHARs are bigger than char, we will just use the
|
|
// wchar buffer to hold the chars, and not worry about the extra
|
|
// room at the end.
|
|
Assert(sizeof(WCHAR) >= sizeof(char));
|
|
|
|
plvfi = &((PNM_FINDITEM)pnmhdr)->lvfi;
|
|
pvThunk1 = (PVOID)plvfi->psz;
|
|
dwThunkSize = lstrlen(pvThunk1) + 1;
|
|
plvfi->psz = (LPWSTR)ProduceAFromW(pci->uiCodePage, plvfi->psz);
|
|
}
|
|
break;
|
|
case LVN_GETDISPINFOW: {
|
|
LV_ITEMW *pitem;
|
|
|
|
pnmhdr->code = LVN_GETDISPINFOA;
|
|
|
|
// Hack Alert! This code assumes that all fields of LV_DISPINFOA and
|
|
// LV_DISPINFOW are exactly the same except for the string pointers.
|
|
|
|
Assert(sizeof(LV_DISPINFOA) == sizeof(LV_DISPINFOW));
|
|
|
|
// Since WCHARs are bigger than char, we will just use the
|
|
// wchar buffer to hold the chars, and not worry about the extra
|
|
// room at the end.
|
|
Assert(sizeof(WCHAR) >= sizeof(char));
|
|
|
|
|
|
// Some sleazebag code (shell32.dll) just changes the pszText
|
|
// pointer to point to the name, so capture the original pointer
|
|
// so we can detect this and not smash their data.
|
|
|
|
pitem = &(((LV_DISPINFOW *)pnmhdr)->item);
|
|
if (!IsFlagPtr(pitem) && (pitem->mask & LVIF_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
pvThunk1 = pitem->pszText;
|
|
dwThunkSize = pitem->cchTextMax;
|
|
}
|
|
break;
|
|
}
|
|
case LVN_ENDLABELEDITW:
|
|
pnmhdr->code = LVN_ENDLABELEDITA;
|
|
bSet = TRUE;
|
|
// Fall through...
|
|
case LVN_BEGINLABELEDITW:
|
|
if (!bSet) {
|
|
pnmhdr->code = LVN_BEGINLABELEDITA;
|
|
bSet = TRUE;
|
|
}
|
|
// Fall through...
|
|
case LVN_SETDISPINFOW: {
|
|
LV_ITEMW *pitem;
|
|
|
|
if (!bSet) {
|
|
pnmhdr->code = LVN_SETDISPINFOA;
|
|
}
|
|
|
|
pitem = &(((LV_DISPINFOW *)pnmhdr)->item);
|
|
|
|
if (!IsFlagPtr(pitem) && (pitem->mask & LVIF_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
pvThunk1 = pitem->pszText;
|
|
dwThunkSize = pitem->cchTextMax;
|
|
|
|
pvThunk2 = ProduceAFromW(pci->uiCodePage, pitem->pszText);
|
|
pitem->pszText = (LPWSTR)pvThunk2;
|
|
}
|
|
break;
|
|
}
|
|
case TVN_SELCHANGINGW:
|
|
pnmhdr->code = TVN_SELCHANGINGA;
|
|
bSet = TRUE;
|
|
case TVN_SELCHANGEDW:
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_SELCHANGEDA;
|
|
bSet = TRUE;
|
|
}
|
|
|
|
/*
|
|
* These msgs have a NM_TREEVIEW with both TV_ITEMs filled in
|
|
|
|
* FALL THROUGH TO TVN_DELETEITEM to thunk itemOld then go on for
|
|
* the other structure.
|
|
*/
|
|
|
|
case TVN_DELETEITEMW: {
|
|
/*
|
|
* This message has a NM_TREEVIEW in lParam with itemOld filled in
|
|
*/
|
|
LPTV_ITEMW pitem;
|
|
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_DELETEITEMA;
|
|
bSet = TRUE;
|
|
}
|
|
|
|
pitem = &(((LPNM_TREEVIEWW)pnmhdr)->itemOld);
|
|
|
|
// thunk itemOld
|
|
if ( (pitem->mask & TVIF_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
pvThunk2 = pitem->pszText;
|
|
pitem->pszText = (LPWSTR)ProduceAFromW(pci->uiCodePage, pvThunk2);
|
|
}
|
|
|
|
// if this is deleteitem then we are done
|
|
if (pnmhdr->code == TVN_DELETEITEMA)
|
|
break;
|
|
|
|
/* FALL THROUGH TO TVN_ITEMEXPANDING to thunk itemNew */
|
|
}
|
|
|
|
case TVN_ITEMEXPANDINGW:
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_ITEMEXPANDINGA;
|
|
bSet = TRUE;
|
|
}
|
|
case TVN_ITEMEXPANDEDW:
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_ITEMEXPANDEDA;
|
|
bSet = TRUE;
|
|
}
|
|
case TVN_BEGINDRAGW:
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_BEGINDRAGA;
|
|
bSet = TRUE;
|
|
}
|
|
case TVN_BEGINRDRAGW: {
|
|
/* these msgs have a NM_TREEVIEW with itemNew TV_ITEM filled in */
|
|
LPTV_ITEMW pitem;
|
|
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_BEGINRDRAGA;
|
|
}
|
|
|
|
pitem = &(((LPNM_TREEVIEWW)pnmhdr)->itemNew);
|
|
|
|
if ( (pitem->mask & TVIF_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
pvThunk1 = pitem->pszText;
|
|
pitem->pszText = (LPWSTR)ProduceAFromW(pci->uiCodePage, pvThunk1);
|
|
}
|
|
break;
|
|
}
|
|
case TVN_SETDISPINFOW:
|
|
pnmhdr->code = TVN_SETDISPINFOA;
|
|
bSet = TRUE;
|
|
case TVN_BEGINLABELEDITW:
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_BEGINLABELEDITA;
|
|
bSet = TRUE;
|
|
}
|
|
case TVN_ENDLABELEDITW: {
|
|
/*
|
|
* All these messages have a TV_DISPINFO in lParam.
|
|
*/
|
|
LPTV_ITEMW pitem;
|
|
|
|
if (!bSet) {
|
|
pnmhdr->code = TVN_ENDLABELEDITA;
|
|
}
|
|
|
|
pitem = &(((TV_DISPINFOW *)pnmhdr)->item);
|
|
|
|
if ((pitem->mask & TVIF_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
pvThunk1 = pitem->pszText;
|
|
dwThunkSize = pitem->cchTextMax;
|
|
|
|
pvThunk2 = ProduceAFromW(pci->uiCodePage, pitem->pszText);
|
|
pitem->pszText = (LPWSTR)pvThunk2;
|
|
}
|
|
break;
|
|
}
|
|
case TVN_GETDISPINFOW: {
|
|
/*
|
|
* All these messages have a TV_DISPINFO in lParam.
|
|
*/
|
|
LPTV_ITEMW pitem;
|
|
|
|
pnmhdr->code = TVN_GETDISPINFOA;
|
|
|
|
pitem = &(((TV_DISPINFOW *)pnmhdr)->item);
|
|
|
|
if ((pitem->mask & TVIF_TEXT) && !IsFlagPtr(pitem->pszText) && pitem->cchTextMax) {
|
|
pvThunk1 = pitem->pszText;
|
|
dwThunkSize = pitem->cchTextMax;
|
|
pvThunk2 = LocalAlloc(LMEM_FIXED, pitem->cchTextMax * sizeof(char));
|
|
pitem->pszText = pvThunk2;
|
|
pitem->pszText[0] = TEXT('\0');
|
|
}
|
|
|
|
break;
|
|
}
|
|
case HDN_ITEMCHANGINGW:
|
|
pnmhdr->code = HDN_ITEMCHANGINGA;
|
|
bSet = TRUE;
|
|
case HDN_ITEMCHANGEDW:
|
|
if (!bSet) {
|
|
pnmhdr->code = HDN_ITEMCHANGEDA;
|
|
bSet = TRUE;
|
|
}
|
|
case HDN_ITEMCLICKW:
|
|
if (!bSet) {
|
|
pnmhdr->code = HDN_ITEMCLICKA;
|
|
bSet = TRUE;
|
|
}
|
|
case HDN_ITEMDBLCLICKW:
|
|
if (!bSet) {
|
|
pnmhdr->code = HDN_ITEMDBLCLICKA;
|
|
bSet = TRUE;
|
|
}
|
|
case HDN_DIVIDERDBLCLICKW:
|
|
if (!bSet) {
|
|
pnmhdr->code = HDN_DIVIDERDBLCLICKA;
|
|
bSet = TRUE;
|
|
}
|
|
case HDN_BEGINTRACKW:
|
|
if (!bSet) {
|
|
pnmhdr->code = HDN_BEGINTRACKA;
|
|
bSet = TRUE;
|
|
}
|
|
case HDN_ENDTRACKW:
|
|
if (!bSet) {
|
|
pnmhdr->code = HDN_ENDTRACKA;
|
|
bSet = TRUE;
|
|
}
|
|
case HDN_TRACKW: {
|
|
HD_ITEMW *pitem;
|
|
|
|
if (!bSet) {
|
|
pnmhdr->code = HDN_TRACKA;
|
|
}
|
|
|
|
pitem = ((HD_NOTIFY *)pnmhdr)->pitem;
|
|
|
|
if ( !IsFlagPtr(pitem) && (pitem->mask & HDI_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
pvThunk1 = pitem->pszText;
|
|
dwThunkSize = pitem->cchTextMax;
|
|
pitem->pszText = (LPWSTR)ProduceAFromW(pci->uiCodePage, pvThunk1);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CBEN_GETDISPINFOW: {
|
|
PNMCOMBOBOXEXW pnmcbe = (PNMCOMBOBOXEXW)pnmhdr;
|
|
|
|
pnmhdr->code = CBEN_GETDISPINFOA;
|
|
|
|
if (pnmcbe->ceItem.mask & CBEIF_TEXT
|
|
&& !IsFlagPtr(pnmcbe->ceItem.pszText) && pnmcbe->ceItem.cchTextMax) {
|
|
pvThunk1 = pnmcbe->ceItem.pszText;
|
|
dwThunkSize = pnmcbe->ceItem.cchTextMax;
|
|
pvThunk2 = LocalAlloc(LMEM_FIXED, pnmcbe->ceItem.cchTextMax * sizeof(char));
|
|
pnmcbe->ceItem.pszText = pvThunk2;
|
|
pnmcbe->ceItem.pszText[0] = TEXT('\0');
|
|
}
|
|
|
|
break;
|
|
}
|
|
case HDN_GETDISPINFOW: {
|
|
LPNMHDDISPINFOW pHDDispInfoW;
|
|
|
|
pnmhdr->code = HDN_GETDISPINFOA;
|
|
pHDDispInfoW = (LPNMHDDISPINFOW) pnmhdr;
|
|
pvThunk1 = pHDDispInfoW->pszText;
|
|
dwThunkSize = pHDDispInfoW->cchTextMax;
|
|
pHDDispInfoW->pszText = GlobalAlloc (GPTR, pHDDispInfoW->cchTextMax * sizeof(char));
|
|
|
|
if (!pHDDispInfoW->pszText) {
|
|
pHDDispInfoW->pszText = (LPWSTR) pvThunk1;
|
|
break;
|
|
}
|
|
|
|
WideCharToMultiByte(pci->uiCodePage, 0, (LPWSTR)pvThunk1, -1, (LPSTR)pHDDispInfoW->pszText, pHDDispInfoW->cchTextMax, NULL, NULL);
|
|
break;
|
|
}
|
|
case TBN_GETBUTTONINFOW:
|
|
{
|
|
LPTBNOTIFYW pTBNW;
|
|
|
|
pnmhdr->code = TBN_GETBUTTONINFOA;
|
|
pTBNW = (LPTBNOTIFYW)pnmhdr;
|
|
|
|
pvThunk1 = pTBNW->pszText;
|
|
dwThunkSize = pTBNW->cchText;
|
|
pvThunk2 = GlobalAlloc (GPTR, pTBNW->cchText * sizeof(char));
|
|
|
|
if (!pvThunk2) {
|
|
break;
|
|
}
|
|
pTBNW->pszText = pvThunk2;
|
|
|
|
WideCharToMultiByte(pci->uiCodePage, 0, (LPWSTR)pvThunk1, -1, (LPSTR)pTBNW->pszText, pTBNW->cchText, NULL, NULL);
|
|
}
|
|
break;
|
|
case TTN_NEEDTEXTW:
|
|
{
|
|
LPTOOLTIPTEXTA lpTTTA;
|
|
LPTOOLTIPTEXTW lpTTTW = (LPTOOLTIPTEXTW) pnmhdr;
|
|
|
|
lpTTTA = GlobalAlloc(GPTR, sizeof(TOOLTIPTEXTA));
|
|
|
|
if (!lpTTTA)
|
|
return 0;
|
|
|
|
lpTTTA->hdr.hwndFrom = lpTTTW->hdr.hwndFrom;
|
|
lpTTTA->hdr.idFrom = lpTTTW->hdr.idFrom;
|
|
lpTTTA->hdr.code = TTN_NEEDTEXTA;
|
|
|
|
lpTTTA->lpszText = lpTTTA->szText;
|
|
lpTTTA->hinst = lpTTTW->hinst;
|
|
lpTTTA->uFlags = lpTTTW->uFlags;
|
|
|
|
pvThunk1 = pnmhdr;
|
|
pnmhdr = (NMHDR FAR *)lpTTTA;
|
|
}
|
|
break;
|
|
case DTN_USERSTRINGW:
|
|
{
|
|
LPNMDATETIMESTRINGW lpDateTimeString = (LPNMDATETIMESTRINGW) pnmhdr;
|
|
|
|
pnmhdr->code = DTN_USERSTRINGA;
|
|
|
|
pvThunk1 = ProduceAFromW(pci->uiCodePage, lpDateTimeString->pszUserString);
|
|
lpDateTimeString->pszUserString = (LPWSTR) pvThunk1;
|
|
}
|
|
break;
|
|
case DTN_WMKEYDOWNW:
|
|
{
|
|
LPNMDATETIMEWMKEYDOWNW lpDateTimeWMKeyDown = (LPNMDATETIMEWMKEYDOWNW) pnmhdr;
|
|
|
|
pnmhdr->code = DTN_WMKEYDOWNA;
|
|
|
|
pvThunk1 = ProduceAFromW(pci->uiCodePage, lpDateTimeWMKeyDown->pszFormat);
|
|
lpDateTimeWMKeyDown->pszFormat = (LPWSTR) pvThunk1;
|
|
}
|
|
break;
|
|
case DTN_FORMATQUERYW:
|
|
{
|
|
LPNMDATETIMEFORMATQUERYW lpDateTimeFormatQuery = (LPNMDATETIMEFORMATQUERYW) pnmhdr;
|
|
|
|
pnmhdr->code = DTN_FORMATQUERYA;
|
|
|
|
pvThunk1 = ProduceAFromW(pci->uiCodePage, lpDateTimeFormatQuery->pszFormat);
|
|
lpDateTimeFormatQuery->pszFormat = (LPWSTR) pvThunk1;
|
|
}
|
|
break;
|
|
case DTN_FORMATW:
|
|
{
|
|
LPNMDATETIMEFORMATW lpDateTimeFormat = (LPNMDATETIMEFORMATW) pnmhdr;
|
|
|
|
pnmhdr->code = DTN_FORMATA;
|
|
|
|
pvThunk1 = ProduceAFromW(pci->uiCodePage, lpDateTimeFormat->pszFormat);
|
|
lpDateTimeFormat->pszFormat = (LPWSTR) pvThunk1;
|
|
}
|
|
break;
|
|
default:
|
|
/* No thunking needed */
|
|
break;
|
|
}
|
|
|
|
lRet = SendMessage(pci->hwndParent, WM_NOTIFY, (WPARAM)id, (LPARAM)pnmhdr);
|
|
|
|
/*
|
|
* All the thunking for Notify Messages happens here
|
|
*/
|
|
switch(pnmhdr->code) {
|
|
case LVN_ODFINDITEMA:
|
|
{
|
|
LV_FINDINFO *plvfi;
|
|
|
|
plvfi = &((PNM_FINDITEM)pnmhdr)->lvfi;
|
|
FreeProducedString( (LPWSTR)plvfi->psz);
|
|
plvfi->psz = pvThunk1;
|
|
}
|
|
break;
|
|
case LVN_GETDISPINFOA: {
|
|
LPWSTR pszW;
|
|
LV_ITEMW *pitem;
|
|
|
|
pitem = &(((LV_DISPINFOW *)pnmhdr)->item);
|
|
|
|
if (!IsFlagPtr(pitem) && (pitem->mask & LVIF_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
if (pvThunk1 == pitem->pszText) {
|
|
pszW = ProduceWFromA(pci->uiCodePage, (LPSTR)(pitem->pszText));
|
|
if (pszW)
|
|
lstrcpy( pitem->pszText, pszW );
|
|
|
|
FreeProducedString(pszW);
|
|
} else {
|
|
|
|
// The pointer has been changed out from underneath us, copy
|
|
// unicode back into the original buffer.
|
|
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)pitem->pszText, -1);
|
|
pitem->pszText = pvThunk1;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case LVN_ENDLABELEDITA:
|
|
case LVN_BEGINLABELEDITA:
|
|
case LVN_SETDISPINFOA: {
|
|
LV_ITEMW *pitem;
|
|
|
|
if (!IsFlagPtr(pvThunk1)) {
|
|
pitem = &(((LV_DISPINFOW *)pnmhdr)->item);
|
|
|
|
if (!IsFlagPtr((LPSTR)pitem->pszText)) {
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)(pitem->pszText), -1);
|
|
}
|
|
|
|
FreeProducedString(pvThunk2);
|
|
pitem->pszText = pvThunk1;
|
|
}
|
|
break;
|
|
}
|
|
case TVN_SELCHANGINGA:
|
|
case TVN_SELCHANGEDA:
|
|
case TVN_DELETEITEMA: {
|
|
LPTV_ITEMW pitem;
|
|
|
|
if ( !IsFlagPtr(pvThunk2) ) {
|
|
pitem = &(((LPNM_TREEVIEWW)pnmhdr)->itemOld);
|
|
|
|
FreeProducedString(pitem->pszText);
|
|
pitem->pszText = pvThunk2;
|
|
}
|
|
|
|
// if this is delitem, then we are done
|
|
if (code == TVN_DELETEITEM)
|
|
break;
|
|
|
|
/* FALL THROUGH TO TVN_ITEMEXPANDING to unthunk itemNew */
|
|
}
|
|
case TVN_ITEMEXPANDINGA:
|
|
case TVN_ITEMEXPANDEDA:
|
|
case TVN_BEGINDRAGA:
|
|
case TVN_BEGINRDRAGA: {
|
|
/* these msgs have a NM_TREEVIEW with itemNew TV_ITEM filled in */
|
|
LPTV_ITEMW pitem;
|
|
|
|
if (!IsFlagPtr(pvThunk1)) {
|
|
pitem = &(((LPNM_TREEVIEWW)pnmhdr)->itemNew);
|
|
|
|
FreeProducedString(pitem->pszText);
|
|
pitem->pszText = pvThunk1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case TVN_SETDISPINFOA:
|
|
case TVN_BEGINLABELEDITA:
|
|
case TVN_ENDLABELEDITA: {
|
|
/* All these messages have a TV_DISPINFO in lParam */
|
|
LPTV_ITEMW pitem;
|
|
|
|
if (!IsFlagPtr(pvThunk1)) {
|
|
pitem = &(((TV_DISPINFOW *)pnmhdr)->item);
|
|
|
|
if (!IsFlagPtr((LPSTR)pitem->pszText)) {
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)(pitem->pszText), -1);
|
|
}
|
|
|
|
FreeProducedString(pvThunk2);
|
|
pitem->pszText = pvThunk1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case TVN_GETDISPINFOA: {
|
|
/*
|
|
* This message has a TV_DISPINFO in lParam that wass filled in
|
|
* during the callback and needs to be unthunked.
|
|
*/
|
|
LPTV_ITEMW pitem;
|
|
|
|
pitem = &(((TV_DISPINFOW *)pnmhdr)->item);
|
|
|
|
if (!IsFlagPtr(pvThunk1) && (pitem->mask & TVIF_TEXT) && !IsFlagPtr(pitem->pszText)) {
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)pitem->pszText, -1);
|
|
pitem->pszText = pvThunk1;
|
|
LocalFree(pvThunk2);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case HDN_ITEMCHANGINGA:
|
|
case HDN_ITEMCHANGEDA:
|
|
case HDN_ITEMCLICKA:
|
|
case HDN_ITEMDBLCLICKA:
|
|
case HDN_DIVIDERDBLCLICKA:
|
|
case HDN_BEGINTRACKA:
|
|
case HDN_ENDTRACKA:
|
|
case HDN_TRACKA: {
|
|
HD_ITEMW *pitem;
|
|
|
|
pitem = ((HD_NOTIFY *)pnmhdr)->pitem;
|
|
|
|
if ( !IsFlagPtr(pitem) && (pitem->mask & HDI_TEXT) && !IsFlagPtr(pvThunk1)) {
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)(pitem->pszText), -1);
|
|
|
|
FreeProducedString(pitem->pszText);
|
|
pitem->pszText = pvThunk1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case CBEN_GETDISPINFOA:
|
|
{
|
|
PNMCOMBOBOXEXW pnmcbeW;
|
|
|
|
pnmcbeW = (PNMCOMBOBOXEXW)pnmhdr;
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)(pnmcbeW->ceItem.pszText), -1);
|
|
|
|
GlobalFree(pnmcbeW->ceItem.pszText);
|
|
pnmcbeW->ceItem.pszText = pvThunk1;
|
|
|
|
}
|
|
break;
|
|
case HDN_GETDISPINFOA:
|
|
{
|
|
LPNMHDDISPINFOW pHDDispInfoW;
|
|
|
|
pHDDispInfoW = (LPNMHDDISPINFOW)pnmhdr;
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)(pHDDispInfoW->pszText), -1);
|
|
|
|
GlobalFree(pHDDispInfoW->pszText);
|
|
pHDDispInfoW->pszText = pvThunk1;
|
|
|
|
}
|
|
break;
|
|
case TBN_GETBUTTONINFOA:
|
|
{
|
|
LPTBNOTIFYW pTBNW;
|
|
|
|
pTBNW = (LPTBNOTIFYW)pnmhdr;
|
|
ConvertAToWN(pci->uiCodePage, pvThunk1, dwThunkSize, (LPSTR)(pTBNW->pszText), -1);
|
|
|
|
pTBNW->pszText = pvThunk1;
|
|
GlobalFree(pvThunk2);
|
|
|
|
}
|
|
break;
|
|
case TTN_NEEDTEXTA:
|
|
{
|
|
LPTOOLTIPTEXTA lpTTTA = (LPTOOLTIPTEXTA) pnmhdr;
|
|
LPTOOLTIPTEXTW lpTTTW = (LPTOOLTIPTEXTW) pvThunk1;
|
|
|
|
ThunkToolTipTextAtoW (lpTTTA, lpTTTW, pci->uiCodePage);
|
|
GlobalFree(lpTTTA);
|
|
}
|
|
break;
|
|
case DTN_USERSTRINGA:
|
|
case DTN_WMKEYDOWNA:
|
|
case DTN_FORMATQUERYA:
|
|
{
|
|
FreeProducedString (pvThunk1);
|
|
}
|
|
break;
|
|
case DTN_FORMATA:
|
|
{
|
|
LPNMDATETIMEFORMATA lpDateTimeFormat = (LPNMDATETIMEFORMATA) pnmhdr;
|
|
|
|
FreeProducedString (pvThunk1);
|
|
|
|
// pszDisplay and szDisplay are special cases.
|
|
if (lpDateTimeFormat->pszDisplay && *lpDateTimeFormat->pszDisplay) {
|
|
// if pszDisplay still points at szDisplay then thunk
|
|
// in place. Otherwise allocate memory and copy the
|
|
// display string. This buffer will be freeded in monthcal.c
|
|
if (lpDateTimeFormat->pszDisplay == lpDateTimeFormat->szDisplay) {
|
|
CHAR szDisplay[64];
|
|
|
|
lstrcpynA (szDisplay, lpDateTimeFormat->szDisplay, 64);
|
|
ConvertAToWN (pci->uiCodePage, (LPWSTR)lpDateTimeFormat->szDisplay, 64, szDisplay, -1);
|
|
} else {
|
|
lpDateTimeFormat->pszDisplay = (LPSTR) ProduceWFromA (pci->uiCodePage, lpDateTimeFormat->pszDisplay);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
/* No thunking needed */
|
|
break;
|
|
}
|
|
|
|
return lRet;
|
|
} else
|
|
#endif
|
|
return(SendMessage(pci->hwndParent, WM_NOTIFY, (WPARAM)id, (LPARAM)pnmhdr));
|
|
}
|
|
|
|
|
|
LRESULT WINAPI SendNotify(HWND hwndTo, HWND hwndFrom, int code, NMHDR FAR* pnmhdr)
|
|
{
|
|
CONTROLINFO ci;
|
|
ci.hwndParent = hwndTo;
|
|
ci.hwnd = hwndFrom;
|
|
ci.bUnicode = FALSE;
|
|
#if TODO
|
|
ci.uiCodePage = CP_ACP;
|
|
#endif
|
|
|
|
// SendNotify is obsolete. New code should call CCSendNotify
|
|
// instead. However, if something does call SendNotify,
|
|
// it will call SendNotifyEx with FALSE as the Unicode parameter,
|
|
// because it probably is ANSI code.
|
|
return CCSendNotify(&ci, code, pnmhdr);
|
|
}
|
|
|
|
|
|
DWORD NEAR PASCAL CICustomDrawNotify(LPCONTROLINFO lpci, DWORD dwStage, LPNMCUSTOMDRAW lpnmcd)
|
|
{
|
|
DWORD dwRet = CDRF_DODEFAULT;
|
|
|
|
// bail if...
|
|
|
|
|
|
// this is an item notification, but an item notification wasn't asked for
|
|
if ((dwStage & CDDS_ITEM) && !(lpci->dwCustom & CDRF_NOTIFYITEMDRAW)) {
|
|
return dwRet;
|
|
}
|
|
|
|
lpnmcd->dwDrawStage = dwStage;
|
|
dwRet = CCSendNotify(lpci, NM_CUSTOMDRAW, &lpnmcd->hdr);
|
|
|
|
// validate the flags
|
|
if (dwRet & ~CDRF_VALIDFLAGS)
|
|
return CDRF_DODEFAULT;
|
|
|
|
return dwRet;
|
|
} |