I am attempting to write a class to handle the creation of a button and it's messages internally. I wish to keep all of the code contained within the class itself. This may be simple or impossible as I am relatively new to Winapi and C++, having used vb.net much more extensively. I was unable to find an example that accomplished this seeming simple conversion. I did find examples suggesting i use an alternate API, or use SetWindowLongPtr, I am told that SetWindowSubclass is the better option. My attempted code is below:
#pragma once
#include <iostream>
#include <Windows.h>
#include <Commctrl.h>
using namespace std;
class button {
public:
bool initialize();
buttton(int x, int y, int length, int width, LPCWSTR text, HWND parent, HINSTANCE hInstance); // This is the constructor
private:
LPCWSTR text = L"Button";
int height = 25;
int width = 100;
int x = 0;
int y = 0;
HWND parent;
HWND thisHandle;
HINSTANCE thisInstance;
bool initialized = false;
LRESULT CALLBACK mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
};
button::button(int x, int y, int height, int width, LPCWSTR text, HWND parent, HINSTANCE hInstance) {
this->x = x;
this->y = y;
this->height = height;
this->width = width;
this->text = text;
this->parent = parent;
thisInstance = hInstance;
}
bool button::initialize()
{
thisHandle = CreateWindowW(
L"BUTTON", // Predefined class; Unicode assumed
text, // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | BS_NOTIFY, // Styles
x, // x position
y, // y position
width, // Button width
height, // Button height
parent, // Parent window
NULL, // No ID.
thisInstance,
NULL); // Pointer not needed.
if (!thisHandle)
{
return false;
}
initialized = true;
//Problem Code****
SetWindowSubclass(thisHandle, mySubClassProc, 1, 0);
//****
return true;
}
LRESULT CALLBACK button::mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
//Code handling messages here.
}
}
This throws the error :
argument of type "LRESULT (__stdcall button::*)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)" is incompatible with parameter of type "SUBCLASSPROC"
I am hoping that someone can explain a simple solution, or suggest an alternative in Winapi, as i wish to learn native windows and C++ and not rely on additional libraries.
You are trying to use a non-static class method as the subclass callback. That will not work, because a non-static class method has a hidden this
parameter that the API will not be able to pass.
To do what you are attempting, you must remove the this
parameter (you can use the dwRefData
parameter of SetWindowSubclass()
instead), by either:
using a static class method:
class button {
public:
bool initialize();
...
private:
...
static LRESULT CALLBACK mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
};
bool button::initialize()
{
...
SetWindowSubclass(thisHandle, mySubClassProc, 1, (DWORD_PTR) this);
return true;
}
LRESULT CALLBACK button::mySubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
button *pThis = (button*) dwRefData;
//Code handling messages here.
}
using a non-member function:
class button {
public:
bool initialize();
...
};
LRESULT CALLBACK myButtonSubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
button *pBtn = (button*) dwRefData;
//Code handling messages here.
}
bool button::initialize()
{
...
SetWindowSubclass(thisHandle, myButtonSubClassProc, 1, (DWORD_PTR) this);
return true;
}