[PATCH 1/7] Use subclass chain for internally used controls
Nikolay Sivov
bunglehead at gmail.com
Wed Dec 23 13:50:26 CST 2009
---
dlls/comctl32/comboex.c | 94 ++++++++++++++++-------------------------
dlls/comctl32/tests/comboex.c | 25 +++++++++++
2 files changed, 61 insertions(+), 58 deletions(-)
diff --git a/dlls/comctl32/comboex.c b/dlls/comctl32/comboex.c
index a2361fd..62178f1 100644
--- a/dlls/comctl32/comboex.c
+++ b/dlls/comctl32/comboex.c
@@ -67,8 +67,6 @@ typedef struct
HWND hwndNotify; /* my parent hwnd */
HWND hwndCombo;
HWND hwndEdit;
- WNDPROC prevEditWndProc; /* previous Edit WNDPROC value */
- WNDPROC prevComboWndProc; /* previous Combo WNDPROC value */
DWORD dwExtStyle;
INT selected; /* index of selected item */
DWORD flags; /* WINE internal flags */
@@ -121,17 +119,15 @@ typedef struct
/* Offset between image and text */
#define CBE_SEP 4
-static const WCHAR COMBOEX_SUBCLASS_PROP[] = {
- 'C','C','C','o','m','b','o','E','x','3','2',
- 'S','u','b','c','l','a','s','s','I','n','f','o',0
-};
+#define COMBO_SUBCLASSID 1
+#define EDIT_SUBCLASSID 2
#define COMBOEX_GetInfoPtr(hwnd) ((COMBOEX_INFO *)GetWindowLongPtrW (hwnd, 0))
-
-/* Things common to the entire DLL */
-static LRESULT WINAPI COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static LRESULT WINAPI COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
+ UINT_PTR uId, DWORD_PTR ref_data);
+static LRESULT CALLBACK COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
+ UINT_PTR uId, DWORD_PTR ref_data);
static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr);
typedef INT (WINAPI *cmp_func_t)(LPCWSTR, LPCWSTR);
@@ -1039,16 +1035,10 @@ static LRESULT COMBOEX_Create (HWND hwnd, CREATESTRUCTA const *cs)
* GetCurrentProcessId()
*/
- /*
- * Setup a property to hold the pointer to the COMBOBOXEX
- * data structure.
- */
- SetPropW(infoPtr->hwndCombo, COMBOEX_SUBCLASS_PROP, hwnd);
- infoPtr->prevComboWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hwndCombo,
- GWLP_WNDPROC, (DWORD_PTR)COMBOEX_ComboWndProc);
+ SetWindowSubclass(infoPtr->hwndCombo, COMBOEX_ComboWndProc, COMBO_SUBCLASSID,
+ (DWORD_PTR)hwnd);
infoPtr->font = (HFONT)SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0);
-
/*
* Now create our own EDIT control so we can position it.
* It is created only for CBS_DROPDOWN style
@@ -1067,14 +1057,9 @@ static LRESULT COMBOEX_Create (HWND hwnd, CREATESTRUCTA const *cs)
* GetWindowThreadProcessId(hwndEdit, &???)
* 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);
}
@@ -1604,7 +1589,10 @@ static void COMBOEX_ResetContent (COMBOEX_INFO *infoPtr)
static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr)
{
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);
infoPtr->edit = 0;
@@ -1729,11 +1717,11 @@ static LRESULT COMBOEX_WindowPosChanging (const COMBOEX_INFO *infoPtr, WINDOWPOS
return 0;
}
-static LRESULT WINAPI
-COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+static LRESULT CALLBACK
+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 (hwndComboex);
+ COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr ((HWND)ref_data);
NMCBEENDEDITW cbeend;
WCHAR edit_text[260];
COLORREF obkc;
@@ -1753,8 +1741,7 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* handle (ignore) the return character */
if (wParam == VK_RETURN) return 0;
/* all other characters pass into the real Edit */
- return CallWindowProcW (infoPtr->prevEditWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
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));
ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
SetBkColor (hDC, obkc);
- return CallWindowProcW (infoPtr->prevEditWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
case WM_KEYDOWN: {
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);
return 0;
default:
- return CallWindowProcW (infoPtr->prevEditWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
case WM_SETFOCUS:
/* remember the focus to set state of icon */
- lret = CallWindowProcW (infoPtr->prevEditWndProc,
- hwnd, uMsg, wParam, lParam);
+ lret = DefSubclassProc(hwnd, uMsg, wParam, lParam);
infoPtr->flags |= WCBE_EDITFOCUSED;
return lret;
@@ -1921,17 +1905,16 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* fall through */
default:
- return CallWindowProcW (infoPtr->prevEditWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
}
-static LRESULT WINAPI
-COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+static LRESULT CALLBACK
+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 (hwndComboex);
+ COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr ((HWND)ref_data);
NMCBEENDEDITW cbeend;
NMMOUSE nmmse;
COLORREF obkc;
@@ -1956,8 +1939,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
* that ComboEx knows this is listbox.
*/
((DRAWITEMSTRUCT *)lParam)->itemState |= ODS_COMBOEXLBOX;
- return CallWindowProcW (infoPtr->prevComboWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
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));
ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
SetBkColor (hDC, obkc);
- return CallWindowProcW (infoPtr->prevComboWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
case WM_SETCURSOR:
/*
@@ -1984,8 +1965,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
nmmse.pt.y = 0;
nmmse.dwHitInfo = lParam;
COMBOEX_Notify (infoPtr, NM_SETCURSOR, (NMHDR *)&nmmse);
- return CallWindowProcW (infoPtr->prevComboWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
case WM_LBUTTONDOWN:
GetClientRect (hwnd, &rect);
@@ -1995,16 +1975,16 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
pt.x = (short)LOWORD(lParam);
pt.y = (short)HIWORD(lParam);
if (PtInRect(&rect, pt))
- return CallWindowProcW (infoPtr->prevComboWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
+
infoPtr->flags |= WCBE_MOUSECAPTURED;
SetCapture(hwnd);
break;
case WM_LBUTTONUP:
if (!(infoPtr->flags & WCBE_MOUSECAPTURED))
- return CallWindowProcW (infoPtr->prevComboWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
+
ReleaseCapture();
infoPtr->flags &= ~WCBE_MOUSECAPTURED;
if (infoPtr->flags & WCBE_MOUSEDRAGGED) {
@@ -2021,8 +2001,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
COMBOEX_NotifyDragBegin(infoPtr, edit_text);
infoPtr->flags |= WCBE_MOUSEDRAGGED;
}
- return CallWindowProcW (infoPtr->prevComboWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
case WM_COMMAND:
switch (HIWORD(wParam)) {
@@ -2166,8 +2145,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
}/* fall through */
default:
- return CallWindowProcW (infoPtr->prevComboWndProc,
- hwnd, uMsg, wParam, lParam);
+ return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
diff --git a/dlls/comctl32/tests/comboex.c b/dlls/comctl32/tests/comboex.c
index 8a1e253..a8d7f79 100644
--- a/dlls/comctl32/tests/comboex.c
+++ b/dlls/comctl32/tests/comboex.c
@@ -27,6 +27,8 @@ static HWND hComboExParentWnd;
static HINSTANCE hMainHinst;
static const char ComboExTestClass[] = "ComboExTestClass";
+static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
+
#define MAX_CHARS 100
static char *textBuffer = NULL;
@@ -356,6 +358,8 @@ static int init(void)
iccex.dwICC = ICC_USEREX_CLASSES;
pInitCommonControlsEx(&iccex);
+ pSetWindowSubclass = (void*)GetProcAddress(hComctl32, (LPSTR)410);
+
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
@@ -390,6 +394,26 @@ static void cleanup(void)
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)
{
if (!init())
@@ -398,6 +422,7 @@ START_TEST(comboex)
test_comboboxex();
test_WM_LBUTTONDOWN();
test_CB_GETLBTEXT();
+ test_comboboxex_subclass();
cleanup();
}
--
1.5.6.5
--=-RBTJ18suSuL3Vi76iMQV--
More information about the wine-patches
mailing list