GetWindowLongPtr fails returning Retrieves the user data - c++

I created win32 wrapper before but I lost the files... So I'm gonna creating them again. The problem is with my router(static window processor).
Here is my code
CFramework *wnd = 0;
// retrieve associated Window instance
wnd = reinterpret_cast<CFramework *>(::GetWindowLongPtr(hWnd, GWL_USERDATA));
// call the windows message handler
wnd->WndProc(hWnd, msg, wParam, lParam);
return true;
When I call GetWindowLongPtr it won't retrieves the user data.
UPDATE:
I also tired this code that uses SetWindowLongPtr
if ( msg == WM_CREATE )
{
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG)((CREATESTRUCT *)lParam)->lpCreateParams );
}
Window *targetApp = (Window*)GetWindowLongPtr( hWnd, GWLP_USERDATA );
if ( targetApp )
{
return targetApp->WndProc( hWnd, msg, wParam, lParam );
}
return DefWindowProc( hWnd, msg, wParam, lParam );
I used my second code.^^^^
I put break point at SetWindow...
It seems it never Get called!

Your window may receive some messages before WM_CREATE. I did something like this a while ago, and there were sizing and positioning messages, along with WM_NCCREATE, that arrived before the WM_CREATE. So you shouldn't expect to see the value there on those messages.
Are you compiling for 32-bit or 64-bit? If 64-bit, then the cast to LONG may be whacking your pointer.
And, as Rup said in the comments, you have to be really certain that nobody else is using WM_USERDATA.

Related

CallWindowProc - strange behavior

It definetly works, but in a strange way.
I'm replacing RichEdit control's procedure with
WNDPROC g_OrigREditText =
(WNDPROC)SetWindowLongPtr( g_hwnd_RichEdit, GWLP_WNDPROC, (LONG_PTR)REditWndProc);
Then, I SendMessage to RichEdit control using EM_REPLACESEL msg, and the text appears in the RichEdit control as it should. But when I replace standard procedure with my own, and process EM_REPLACESEL in mine own procedure, then the following scenario happens. Here's the code:
LRESULT CALLBACK REditWndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg )
{
case EM_REPLACESEL:
{
int sdfsdf = 0;
CallWindowProc( (WNDPROC)g_OrigREditText, hwnd, msg, wp, lp );
break;
}
default:
return DefWindowProc( hwnd, msg, wp, lp);
break;
}
return 0;
}
Ok, I send an EM_REPLACESEL message to the RichEdit as usual and it works well, cos I catch operation pointer in "case EM_REPLACESEL" block.
Then CallWindowProc should do its job by passing parameters to the next procedure in the chain, but instead nothing happens, the text doesn't appear in a RichEdit control. Looks like something prevent the message to be passed to old procedure, but! if I replace g_OrigREditText with REditWndProc, then I catch the same UINT msg again, so it definetely pass parameters further, like it should.
So what's wrong with CallWindowProc or with my code, where should I dig to fix the problem?
The whole thing is called "subclassing" and this can be useful .
usually there are more events that occurs in relating with one message so change your code to this
LRESULT CALLBACK REditWndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
if( msg == EM_REPLACESEL)
{
// whatever you want
return TRUE;// comment this
// if you want to give it to the original proc.
}
return CallWindowProc( g_OrigREditText, hwnd, msg, wp, lp );
}

Low Level keyboard hook never catches WM_KEYDOWN

I'm trying to create macro application that will start running certain operations when key is pressed (system wide shortcut). I did created Windows Form Application with Visual Studio 2012. When form is loaded keyboard hook is installed:
HookHandle = SetWindowsHookEx( WH_KEYBOARD_LL, (HOOKPROC)keyboardHookHandler, GetModuleHandle(NULL), NULL);
if( HookHandle == 0){
MessageBox::Show("Error setting hook!");
}
My hook callback function is:
public: static LRESULT CALLBACK keyboardHookHandler( int code, WPARAM wParam, LPARAM lParam ) {
if(code>=0 && wParam == WM_KEYDOWN){
MessageBox::Show("Key Down");
}
return CallNextHookEx( HookHandle, code, wParam, lParam);
}
When I do compile application and run it message box is never shown. More to say I know this call back function is fired but wParam always contains value 45 (I did checked and none of those WM constants that should be returned has value 45). Also after few key events application crashes.
What is the reason why this code doesn't work like it should to?
Update:
I did removed cast to HOOKPROC and changed it to delegated procedure:
private:
delegate LRESULT CALLBACK HOOKPROC( int code, WPARAM wParam, LPARAM lParam );
HOOKPROC^ keyboardHookProcedure;
And hook setting to:
keyboardHookProcedure = gcnew HOOKPROC(this, &MyForm::keyboardHookHandler);
HookHandle = SetWindowsHookEx( WH_KEYBOARD_LL, keyboardHookProcedure, GetModuleHandle(NULL), NULL);
But now I have this problem:
error C2664: 'SetWindowsHookExW' : cannot convert parameter 2 from 'WindowsFormTest::MyForm::HOOKPROC ^' to 'HOOKPROC'
If you're trying to catch a unique key combination globally, it might be simpler to use RegisterHotKey. It defines a system-wide hot key with no need for hooks or anything special. It is going to override the foreground process handling, so this won't be ideal if you're trying to register a common key combo.

C++ Windows API - how to use a ListView's default WIndows Proc?

Okay, I have a ListView and I've just worked out how to manually set it's Callback procedure:
// Sets the list view procedure
listproc = (D_ListView *) LocalAlloc(LMEM_FIXED, sizeof(D_ListView));
listproc->oldproc = (WNDPROC)SetWindowLongPtr(g_hList, GWL_WNDPROC, (LONG)&ListViewProc);
SetWindowLongPtr(g_hList, GWL_USERDATA, (LONG)&listproc);
I used a code example I found - D_ListView is just a struct with a WNDPROC variable called oldproc.
Anyhow, I'm sending messages to my ListView to add items. But I don't want to handle the ADD messages manually, I want to pass them onto the ListView's default procedure, and only handle messages that I need to over-ride the functionality for.
LRESULT CALLBACK ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
// Just a test - we're getting this message so it worked
case LVM_INSERTCOLUMN:
{
cout << "CREATED" << endl;
}
}
WNDPROC* wp;
wp = (WNDPROC*)(::GetWindowLongPtr(hwnd, GWL_WNDPROC));
return ::CallWindowProc(*wp, hwnd, msg, wParam, lParam);
}
In the above, I don't want to deal withe LVM_INSERTCOLUMN: I just want to pass it on.
Any one able to help?
Thanks,
Rob
use getWindowLongPtr (...GWL_USERDATA) to get the pointer to your D_ListView instance and then forward any unwanted messages to oldproc
::CallWindowProc(*listproc->oldproc, hwnd, msg, wParam, lParam);

Use class member as WNDPROC/DLGPROC with or without global

I'll go ahead and give a summary to this, how can I use a dialog procedure that is a member of a class? I am creating a window wrapper class, but CreateDialogParam needs a global dialog procedure, so I tried this workaround:
I have done a bit of searching on this topic. I am making a Dialog class which I am subclassing to make a CMainWnd and then instantiating that. In the Dialog class I have a member function defined as INT_PTR CALLBACK Dialog::cb_proc(HWND,UINT,WPARAM,LPARAM). Now, I know that windows must have a global function as a callback procedure.
So I made a std::map<HWND,Dialog*> DlgProcs map to associate the dialogs window handle with its Dialog class pointer.
And a INT_PTR CALLBACK DlgMainProc(HWND,UINT,WPARAM,LPARAM) so I could pass that to CreateDialogParam(). In the body of DlgMainProc(...) I search the map for using the hWnd parameter to find the Dialog* and return its cb_proc(..) member.
My problem is that none of the messages get processed, this is because the member procedure in my Dialog class never gets called. Even though when I put a MessageBox() in DlgMainProc inside a if (DlgProcs.find(hWnd) != DlgProcs.end()) { statement, the messagebox is displayed, over and over again until I have to abort the program from Visual Studio 2008. Which tells me that it is finding the hWnd in my map. The weird thing is it also does this if I put it in the else statement after that, which contradictingly tells me it is NOT finding the hWnd in the map.
If I put a messagebox in the cb_proc member function it does not get displayed at all. But during this I never get any compiler, linker, or runtime errors. When I remove the messagebox from it (as to not have to abort the program, it was just for debugging purposes) the program runs but no messages get processed, the X button does not close the program, button clicks do nothing.
Here is the PasteBin code: http://pastebin.com/GsGUBpZU
Btw, I have no problem subclassing this, my window is created fine, just no messages are processed, cb_proc just never gets called.
EDIT: Here is the relevant parts of the code
map<HWND,Dialog*> g_DlgProcs;
INT_PTR CALLBACK g_MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (g_DlgProcs.find(hWnd) != g_DlgProcs.end()) {
Alert("blah"); // Gets executed repeatedly
return g_DlgProcs[hWnd]->cb_proc(hWnd, msg, wParam, lParam);
} else {
Alert("blah"); // Removing the above alert, this gets
// executed repeatedly, erm, as well.. O.o strange
return FALSE;
}
}
Dialog::Dialog(int id, HWND parent /* = HWND_DESKTOP */) {
_id = id;
_parent = parent;
// Tried this before CreateDialogParam
g_DlgProcs.insert(make_pair(_handle, this));
_handle = CreateDialogParam(
(HINSTANCE)GetModuleHandle(NULL),
MAKEINTRESOURCE(id), _parent,
(DLGPROC)g_MainDlgProc, NULL
);
// Then tried it after CreateDialogParam
g_DlgProcs.insert(make_pair(_handle, this));
}
INT_PTR CALLBACK Dialog::cb_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
Alert("blah"); // Never gets executed
bool handled = true;
switch (msg)
{
case WM_INITDIALOG:
OnInitialize();
break;
case WM_COMMAND:
if (HIWORD(wParam) == 0 || HIWORD(wParam) == 1) {
OnMenuCommand((HIWORD(wParam) == 1), (int)LOWORD(wParam));
} else {
OnCtrlCommand((int)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);
}
break;
case WM_NOTIFY:
{
LPNMHDR head = (LPNMHDR)lParam;
OnNotification(head->code, head->idFrom, head->hwndFrom);
}
break;
case WM_CLOSE:
OnClose(); // DestroyWindow(_handle)
break;
case WM_DESTROY:
OnDestroy(); // PostQuitMessage(0)
default:
handled = ProcessMsg(msg, wParam, lParam);
}
// Convert bool to Windows BOOL enum
return ((handled == true) ? TRUE : FALSE);
}
Does anybody know why it never gets called? Or maybe just guide me to another way to use a member function as a DLGPROC?
The standard solution is to pass your this pointer as the last parameter to Create,DialogParam, stash it in DWLP_USER in your WM_INITDIALOG handler, and retrieve it from DWLP_USER thereafter. Basically you use DWLP_USER as your map.
I tried your code and it worked: cb_proc gets called. You will miss any messages (e.g. WM_INITDIALOG) that get sent before CreateDialogParam returns.
You can fix the latter problem by adding the window handle and the object to the map in g_MainDlgProc. If you get a message for an unknown window, you know it belongs to the window you're creating; put the object in a global and you can add the handle/object to the map.
I'm just adding this here in case someone finds it useful; using the magic of C++11 lambdas and templates you can have a simple wrapper template that means you don't have to continually rewrite the boiler-plate code for saving and loading userdata in window and dialog box procedures.
Here's an example for the DialogBoxParam function, but the same technique can be applied to CreateDialogParam and CreateWindowEx as well.
template <typename T, INT_PTR (T::*P)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)>
INT_PTR DialogBoxThis(T* pThis, HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent)
{
return ::DialogBoxParam(hInstance, lpTemplateName, hWndParent, [](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -> INT_PTR {
if (uMsg == WM_INITDIALOG) SetWindowLongPtr(hWnd, DWLP_USER, lParam);
T* pThis = reinterpret_cast<T*>(GetWindowLongPtr(hWnd, DWLP_USER));
return pThis ? (pThis->*P)(hWnd, uMsg, wParam, lParam) : FALSE;
}, reinterpret_cast<LPARAM>(pThis));
}
You would use it like this:
class MyClass
{
INT_PTR MyDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
// from inside MyClass, we can show a dialog that uses member function MyDlgProc as the dialog procedure
// note it is NOT a static function
DialogBoxThis<MyClass, &MyClass::MyDlgProc>(this, hInstance,
MAKEINTRESOURCE(IDD_MYDIALOG), hWndParent);

Weird bug with WndProc and DispatchMessage. Member Functions don't exist?

So a bit of a weird bug going on when getting a WM_KEYDOWN msg in my Window class.
I have a Global WndProc function that determines which window instance it is and sends the message to it's own local WndProc function.
//Every Windows Message will hit this function.
LRESULT CALLBACK GlobalWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
//Get the Window Instance from the userdata
Window* targetWindow = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
//If no window exists, then it must be the first time so we should set it
if (!targetWindow) {
//First let's try and extract the Window instance pointer from the lparam
CREATESTRUCT* createStruct = (CREATESTRUCT*)lparam;
if (createStruct) {
targetWindow = (Window*)createStruct->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)targetWindow);
}
else {
//It was some other message which we just can't deal with right now
return DefWindowProc(hwnd, msg, wparam, lparam);
}
}
//Now we can pipe it to the Window's local wnd proc function
return targetWindow->LocalWndProc(hwnd, msg, wparam, lparam);
}
And my local wndproc looks like this:
LRESULT CALLBACK Window::LocalWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
switch (msg) {
case WM_KEYDOWN:
ToggleFullScreen(!m_fullScreen);
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
break;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
}
So it's pretty simple at this point. If any key is pressed, the window should call its member function ToggleFullScreen.
Now for some reason when i run this and I hit any key on the keyboard, I get an exception fault:
Unhandled exception at 0x77c015ee in Athena_Debug.exe: 0xC0000005: Access violation reading location 0x0000012d.
With CallStack:
ntdll.dll!77c015ee()
ntdll.dll!77bf015e()
user32.dll!7588788a()
Athena_Debug.exe!Athena::Window::HandleWindowsMessage() Line 195 + 0xc bytes C++
Athena_Debug.exe!Athena::AthenaCore::StartEngine() Line 96 + 0x12 bytes C++
Athena_Debug.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 44 C++
Athena_Debug.exe!__tmainCRTStartup() Line 547 + 0x2c bytes C
Athena_Debug.exe!WinMainCRTStartup() Line 371 C
kernel32.dll!7702339a()
The line it actually breaks on is the DispatchMessage(&msg) line located here:
MSG Window::HandleWindowsMessage() {
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
if (m_realTime) {
PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE);
}
else {
GetMessage(&msg, m_hwnd, 0, 0);
}
if (msg.message != WM_NULL) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg;
}
So the interesting thing is that if I comment out ToggleFullScreen and instead put an OutputDebugTrace there it works just fine and outputs the debug trace. It appears like it can't resolve the function for an instance? If I comment everything out in ToggleFullScreen, it still crashes. If i create a brand new function that does nothing and call it in response to WM_KEYDOWN it still errors.
Anyone have any idea why this is happening or some ideas on how I can go about fixing it?
Thanks!
I would be guessing that you have wrong pointer obntained from GetWindowLongPtr, as it was not set by SetWindowLongPtr. As I wrote in my comment, you should not test if it's empty (I have no idea what is there by default but i wouldn't assume anything.), but set it when you recieve WM_CRERATE (which is guaranteed to be the first message sent to a window). Have you tested if SetWindowLongPtr is acctually called?
Other messages are not dependent on any contents of Window class, so they are working well with wrong this pointer - it is an error to call method for wrong pointer, but if method is not actually using it, it will still work well.
EDIT:
Another possbile cause: Why are you not using result value from PeekMessage? i see that you are testing for WM_NULL, which should be 0 at this point (you are zeroing memory), but PeekMessage does not guarantee that it's not touching MSG structure even if it's not retrieving anything. Using PeekMessage result should be used at all times. Plus zeroing memory is rather inefficient at this point.
The first message does not have to be WM_NCCREATE (or WM_CREATE), you have to be prepared to get WM_SIZE or WM_GETMINMAXINFO (and probably other messages) before any create message!
In your code you would change if (createStruct) { to if (WM_NCCREATE==msg && createStruct) {...
You can see this in Raymond Chen's scratch program.
Your WindowProc callback should look more like this:
//Every Windows Message will hit this function.
LRESULT CALLBACK GlobalWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
Window* targetWindow;
if (msg == WM_CREATE)
{
//extract the Window instance pointer from the lparam
CREATESTRUCT* createStruct = (CREATESTRUCT*)lparam;
targetWindow = (Window*)createStruct->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)targetWindow);
}
else
{
//Get the Window Instance from the userdata
targetWindow = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (targetWindow)
{
//Now we can pipe it to the Window's local wnd proc function
return targetWindow->LocalWndProc(hwnd, msg, wparam, lparam);
}
//It was some other message which we just can't deal with right now
return DefWindowProc(hwnd, msg, wparam, lparam);
}