Subclassing Button Control within a Class
I created my own custom GUI button class for use in Windows Mobile apps. Realizing that I needed some finer control and to remove the double-click annoyance, I figured all I need to do is subclass it like I always have.
But, being that I have encapsulated everything into a Class though, seems to have complicated the matter.
Below is a snippet of what I want to do
// Graphic button clas开发者_高级运维s for Wizard(ing) dialogs.
class CButtonUXnav
{
private:
// Local subclasses of controls.
WNDPROC wpOldButton; // Handle to the original callback.
LRESULT CALLBACK Button_WndProc (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
. . .
int CButtonUXnav::CreateButton (LPCTSTR lpButtonText, int x, int y, int iWidth, int iHeight, bool gradeL2R)
{
xLoc = x;
yLoc = y;
nWidth = iWidth;
nHeight = iHeight;
wcscpy (wszButtonText, lpButtonText);
PaintButtonInternals (x, y, iWidth, iHeight, gradeL2R);
hButton = CreateWindow (L"BUTTON", wszButtonText,
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | BS_OWNERDRAW,
xLoc, yLoc, nWidth, nHeight,
hWndParent, IDbutn, hInstance, NULL);
// Subclass
// (to remove double-click annoyance.)
wpOldButton = (WNDPROC)GetWindowLong (hButton, GWL_WNDPROC);
if (wpOldButton == 0)
return 1;
// Insert our own callback.
SetWindowLong (hButton, GWL_WNDPROC, (LONG)Button_WndProc);
return 0;
}
But I can't seem to escape resolving this error:
error C2440: 'type cast' : cannot convert from 'LRESULT (__cdecl CButtonUXnav::* )(HWND,UINT,WPARAM,LPARAM)' to 'LONG'
Your thoughts?
You're trying to pass a member function to an outside entity to call it, and that's impossible.
Try to imagine that someone is calling CallWindowProc(MyEditHandle, ...)
. On which object (instance) of CButtonUXnav should Button_WndProc operate on? What would be its this
pointer?
If you really want to have the callback function as your class' member, you must declare it as static
, rendering it accessible from outside, but able to access only static member variables of CButtonUXnav.
To tackle this, bind a pointer to your CButtonNXnav with the edit's window handle using SetWindowLong(hWnd, GWL_USERDATA, &CButtonUXnav)
, and that would solve your problem.
EDIT:
You actually need three things:
- Have the callback function declared as static:
static Button_WndProc(HWND,UINT,WPARAM,LPARAM);
- Store a pointer to your
CButtonUXnav
object when performing the subclass:
SetWindowLong(hWnd, GWL_USERDATA, (LONG)this);
- Retrieve that pointer from within the static callback to act upon it;
CButtonUXnav *pMyObj = (CButtonUXnav*)GetWindowLong(hWnd, GWL_USERDATA);
(note: It might be more straight-forward to:)
CButtonUXnav& pMyObj = *(CButtonUXnav*)GetWindowLong(hWnd, GWL_USERDATA);
Hope this does it :)
精彩评论