comctl32/comboex: Use subclass chain for internally used controls.

This commit is contained in:
Nikolay Sivov 2009-12-23 22:50:26 +03:00 committed by Alexandre Julliard
parent b67820cea6
commit ecc89bf6ef
2 changed files with 61 additions and 58 deletions

View File

@ -67,8 +67,6 @@ typedef struct
HWND hwndNotify; /* my parent hwnd */ HWND hwndNotify; /* my parent hwnd */
HWND hwndCombo; HWND hwndCombo;
HWND hwndEdit; HWND hwndEdit;
WNDPROC prevEditWndProc; /* previous Edit WNDPROC value */
WNDPROC prevComboWndProc; /* previous Combo WNDPROC value */
DWORD dwExtStyle; DWORD dwExtStyle;
INT selected; /* index of selected item */ INT selected; /* index of selected item */
DWORD flags; /* WINE internal flags */ DWORD flags; /* WINE internal flags */
@ -121,17 +119,15 @@ typedef struct
/* Offset between image and text */ /* Offset between image and text */
#define CBE_SEP 4 #define CBE_SEP 4
static const WCHAR COMBOEX_SUBCLASS_PROP[] = { #define COMBO_SUBCLASSID 1
'C','C','C','o','m','b','o','E','x','3','2', #define EDIT_SUBCLASSID 2
'S','u','b','c','l','a','s','s','I','n','f','o',0
};
#define COMBOEX_GetInfoPtr(hwnd) ((COMBOEX_INFO *)GetWindowLongPtrW (hwnd, 0)) #define COMBOEX_GetInfoPtr(hwnd) ((COMBOEX_INFO *)GetWindowLongPtrW (hwnd, 0))
static LRESULT CALLBACK COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
/* Things common to the entire DLL */ UINT_PTR uId, DWORD_PTR ref_data);
static LRESULT WINAPI COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
static LRESULT WINAPI COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); UINT_PTR uId, DWORD_PTR ref_data);
static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr); static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr);
typedef INT (WINAPI *cmp_func_t)(LPCWSTR, LPCWSTR); typedef INT (WINAPI *cmp_func_t)(LPCWSTR, LPCWSTR);
@ -1039,16 +1035,10 @@ static LRESULT COMBOEX_Create (HWND hwnd, CREATESTRUCTA const *cs)
* GetCurrentProcessId() * GetCurrentProcessId()
*/ */
/* SetWindowSubclass(infoPtr->hwndCombo, COMBOEX_ComboWndProc, COMBO_SUBCLASSID,
* Setup a property to hold the pointer to the COMBOBOXEX (DWORD_PTR)hwnd);
* data structure.
*/
SetPropW(infoPtr->hwndCombo, COMBOEX_SUBCLASS_PROP, hwnd);
infoPtr->prevComboWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hwndCombo,
GWLP_WNDPROC, (DWORD_PTR)COMBOEX_ComboWndProc);
infoPtr->font = (HFONT)SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0); infoPtr->font = (HFONT)SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0);
/* /*
* Now create our own EDIT control so we can position it. * Now create our own EDIT control so we can position it.
* It is created only for CBS_DROPDOWN style * It is created only for CBS_DROPDOWN style
@ -1067,14 +1057,9 @@ static LRESULT COMBOEX_Create (HWND hwnd, CREATESTRUCTA const *cs)
* GetWindowThreadProcessId(hwndEdit, &???) * GetWindowThreadProcessId(hwndEdit, &???)
* GetCurrentProcessId() * GetCurrentProcessId()
*/ */
SetWindowSubclass(infoPtr->hwndEdit, COMBOEX_EditWndProc, EDIT_SUBCLASSID,
(DWORD_PTR)hwnd);
/*
* Setup a property to hold the pointer to the COMBOBOXEX
* data structure.
*/
SetPropW(infoPtr->hwndEdit, COMBOEX_SUBCLASS_PROP, hwnd);
infoPtr->prevEditWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hwndEdit,
GWLP_WNDPROC, (DWORD_PTR)COMBOEX_EditWndProc);
infoPtr->font = (HFONT)SendMessageW(infoPtr->hwndCombo, WM_GETFONT, 0, 0); infoPtr->font = (HFONT)SendMessageW(infoPtr->hwndCombo, WM_GETFONT, 0, 0);
} }
@ -1604,7 +1589,10 @@ static void COMBOEX_ResetContent (COMBOEX_INFO *infoPtr)
static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr) static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr)
{ {
if (infoPtr->hwndCombo) if (infoPtr->hwndCombo)
DestroyWindow (infoPtr->hwndCombo); RemoveWindowSubclass(infoPtr->hwndCombo, COMBOEX_ComboWndProc, COMBO_SUBCLASSID);
if (infoPtr->hwndEdit)
RemoveWindowSubclass(infoPtr->hwndEdit, COMBOEX_EditWndProc, EDIT_SUBCLASSID);
Free (infoPtr->edit); Free (infoPtr->edit);
infoPtr->edit = 0; infoPtr->edit = 0;
@ -1729,11 +1717,11 @@ static LRESULT COMBOEX_WindowPosChanging (const COMBOEX_INFO *infoPtr, WINDOWPOS
return 0; return 0;
} }
static LRESULT WINAPI static LRESULT CALLBACK
COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
UINT_PTR uId, DWORD_PTR ref_data)
{ {
HWND hwndComboex = GetPropW(hwnd, COMBOEX_SUBCLASS_PROP); COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr ((HWND)ref_data);
COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwndComboex);
NMCBEENDEDITW cbeend; NMCBEENDEDITW cbeend;
WCHAR edit_text[260]; WCHAR edit_text[260];
COLORREF obkc; COLORREF obkc;
@ -1753,8 +1741,7 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* handle (ignore) the return character */ /* handle (ignore) the return character */
if (wParam == VK_RETURN) return 0; if (wParam == VK_RETURN) return 0;
/* all other characters pass into the real Edit */ /* all other characters pass into the real Edit */
return CallWindowProcW (infoPtr->prevEditWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
case WM_ERASEBKGND: case WM_ERASEBKGND:
/* /*
@ -1766,8 +1753,7 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
TRACE("erasing (%s)\n", wine_dbgstr_rect(&rect)); TRACE("erasing (%s)\n", wine_dbgstr_rect(&rect));
ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0); ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
SetBkColor (hDC, obkc); SetBkColor (hDC, obkc);
return CallWindowProcW (infoPtr->prevEditWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
case WM_KEYDOWN: { case WM_KEYDOWN: {
INT_PTR oldItem, selected, step = 1; INT_PTR oldItem, selected, step = 1;
@ -1889,16 +1875,14 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
SendMessageW (infoPtr->hwndSelf, CB_SETCURSEL, oldItem + step, 0); SendMessageW (infoPtr->hwndSelf, CB_SETCURSEL, oldItem + step, 0);
return 0; return 0;
default: default:
return CallWindowProcW (infoPtr->prevEditWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
} }
return 0; return 0;
} }
case WM_SETFOCUS: case WM_SETFOCUS:
/* remember the focus to set state of icon */ /* remember the focus to set state of icon */
lret = CallWindowProcW (infoPtr->prevEditWndProc, lret = DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
infoPtr->flags |= WCBE_EDITFOCUSED; infoPtr->flags |= WCBE_EDITFOCUSED;
return lret; return lret;
@ -1921,17 +1905,16 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* fall through */ /* fall through */
default: default:
return CallWindowProcW (infoPtr->prevEditWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
} }
} }
static LRESULT WINAPI static LRESULT CALLBACK
COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
UINT_PTR uId, DWORD_PTR ref_data)
{ {
HWND hwndComboex = GetPropW(hwnd, COMBOEX_SUBCLASS_PROP); COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr ((HWND)ref_data);
COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwndComboex);
NMCBEENDEDITW cbeend; NMCBEENDEDITW cbeend;
NMMOUSE nmmse; NMMOUSE nmmse;
COLORREF obkc; COLORREF obkc;
@ -1956,8 +1939,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
* that ComboEx knows this is listbox. * that ComboEx knows this is listbox.
*/ */
((DRAWITEMSTRUCT *)lParam)->itemState |= ODS_COMBOEXLBOX; ((DRAWITEMSTRUCT *)lParam)->itemState |= ODS_COMBOEXLBOX;
return CallWindowProcW (infoPtr->prevComboWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
case WM_ERASEBKGND: case WM_ERASEBKGND:
/* /*
@ -1969,8 +1951,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
TRACE("erasing (%s)\n", wine_dbgstr_rect(&rect)); TRACE("erasing (%s)\n", wine_dbgstr_rect(&rect));
ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0); ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
SetBkColor (hDC, obkc); SetBkColor (hDC, obkc);
return CallWindowProcW (infoPtr->prevComboWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
case WM_SETCURSOR: case WM_SETCURSOR:
/* /*
@ -1984,8 +1965,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
nmmse.pt.y = 0; nmmse.pt.y = 0;
nmmse.dwHitInfo = lParam; nmmse.dwHitInfo = lParam;
COMBOEX_Notify (infoPtr, NM_SETCURSOR, (NMHDR *)&nmmse); COMBOEX_Notify (infoPtr, NM_SETCURSOR, (NMHDR *)&nmmse);
return CallWindowProcW (infoPtr->prevComboWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
GetClientRect (hwnd, &rect); GetClientRect (hwnd, &rect);
@ -1995,16 +1975,16 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
pt.x = (short)LOWORD(lParam); pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam); pt.y = (short)HIWORD(lParam);
if (PtInRect(&rect, pt)) if (PtInRect(&rect, pt))
return CallWindowProcW (infoPtr->prevComboWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
infoPtr->flags |= WCBE_MOUSECAPTURED; infoPtr->flags |= WCBE_MOUSECAPTURED;
SetCapture(hwnd); SetCapture(hwnd);
break; break;
case WM_LBUTTONUP: case WM_LBUTTONUP:
if (!(infoPtr->flags & WCBE_MOUSECAPTURED)) if (!(infoPtr->flags & WCBE_MOUSECAPTURED))
return CallWindowProcW (infoPtr->prevComboWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
ReleaseCapture(); ReleaseCapture();
infoPtr->flags &= ~WCBE_MOUSECAPTURED; infoPtr->flags &= ~WCBE_MOUSECAPTURED;
if (infoPtr->flags & WCBE_MOUSEDRAGGED) { if (infoPtr->flags & WCBE_MOUSEDRAGGED) {
@ -2021,8 +2001,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
COMBOEX_NotifyDragBegin(infoPtr, edit_text); COMBOEX_NotifyDragBegin(infoPtr, edit_text);
infoPtr->flags |= WCBE_MOUSEDRAGGED; infoPtr->flags |= WCBE_MOUSEDRAGGED;
} }
return CallWindowProcW (infoPtr->prevComboWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
case WM_COMMAND: case WM_COMMAND:
switch (HIWORD(wParam)) { switch (HIWORD(wParam)) {
@ -2166,8 +2145,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break; break;
}/* fall through */ }/* fall through */
default: default:
return CallWindowProcW (infoPtr->prevComboWndProc, return DefSubclassProc(hwnd, uMsg, wParam, lParam);
hwnd, uMsg, wParam, lParam);
} }
return 0; return 0;
} }

View File

@ -27,6 +27,8 @@ static HWND hComboExParentWnd;
static HINSTANCE hMainHinst; static HINSTANCE hMainHinst;
static const char ComboExTestClass[] = "ComboExTestClass"; static const char ComboExTestClass[] = "ComboExTestClass";
static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
#define MAX_CHARS 100 #define MAX_CHARS 100
static char *textBuffer = NULL; static char *textBuffer = NULL;
@ -356,6 +358,8 @@ static int init(void)
iccex.dwICC = ICC_USEREX_CLASSES; iccex.dwICC = ICC_USEREX_CLASSES;
pInitCommonControlsEx(&iccex); pInitCommonControlsEx(&iccex);
pSetWindowSubclass = (void*)GetProcAddress(hComctl32, (LPSTR)410);
wc.style = CS_HREDRAW | CS_VREDRAW; wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
wc.cbWndExtra = 0; wc.cbWndExtra = 0;
@ -390,6 +394,26 @@ static void cleanup(void)
UnregisterClassA(ComboExTestClass, GetModuleHandleA(NULL)); UnregisterClassA(ComboExTestClass, GetModuleHandleA(NULL));
} }
static void test_comboboxex_subclass(void)
{
HWND hComboEx, hCombo, hEdit;
hComboEx = createComboEx(WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN);
hCombo = (HWND)SendMessage(hComboEx, CBEM_GETCOMBOCONTROL, 0, 0);
ok(hCombo != NULL, "Failed to get internal combo\n");
hEdit = (HWND)SendMessage(hComboEx, CBEM_GETEDITCONTROL, 0, 0);
ok(hEdit != NULL, "Failed to get internal edit\n");
if (pSetWindowSubclass)
{
ok(GetPropA(hCombo, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
ok(GetPropA(hEdit, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
}
DestroyWindow(hComboEx);
}
START_TEST(comboex) START_TEST(comboex)
{ {
if (!init()) if (!init())
@ -398,6 +422,7 @@ START_TEST(comboex)
test_comboboxex(); test_comboboxex();
test_WM_LBUTTONDOWN(); test_WM_LBUTTONDOWN();
test_CB_GETLBTEXT(); test_CB_GETLBTEXT();
test_comboboxex_subclass();
cleanup(); cleanup();
} }