Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 19, 2009 amazing function behavior | ||||
---|---|---|---|---|
| ||||
Function is never called but why? look at: window.Window.wndProc : case WM.LBUTTONDOWN //______________________________________________ module window; private import base; private import structs; private static import user32; private static import kernel32; private static import gdi32; private: extern (Windows) static dword wndProc(ptr o_hwnd, dword o_msg, dword o_wparam, dword o_lparam){ alias user32.EWindowMessage WM; auto l_wnd = cast(Window*)user32.getWindowLong(o_hwnd, 0x00); if(o_msg == WM.NCCREATE){ user32.setWindowLong(o_hwnd, 0x00, *(cast(dword*)o_lparam)); } else if(l_wnd is null){ return 0x00; } return (cast(Window*)user32.getWindowLong(o_hwnd, 0x00)).wndProc(o_hwnd, o_msg, o_wparam, o_lparam); } public: class Window{ private const ptr handle; void onMouseDown(MouseEventArgs o_mea){ user32.messageBox(null, cast(wstr)"Window", cast(wstr)"msg", 0x00); } this(){ WINWndClassEx wndClass; wndClass.size = 0x00000030; wndClass.style = 0x00000003; wndClass.wndProc = cast(ptr)&.wndProc; wndClass.clsExtraBytes = 0x00000000; wndClass.wndExtraBytes = 0x00000004; wndClass.hInstance = kernel32.getModuleHandle(null); wndClass.hIcon = user32.loadIcon(null, 0x00007F00); wndClass.hCursor = user32.loadCursor(null, 0x00007F00); wndClass.hbrBackground = gdi32.getStockObject(0x00000000); wndClass.menuName = null; wndClass.className = cast(wstr)"clsname"; wndClass.hIconSm = user32.loadIcon(null, 0x00007F00); if(!user32.registerClassEx(cast(ptr)&wndClass)){ if(kernel32.getLastError() != 0x0582){ user32.messageBox(null, user32.translateErrorCode(kernel32.getLastError()), cast(wstr)"error", 0x00000000); assert(false, "window class registering failed"); } } handle = user32.createWindowEx( 0, wndClass.className, cast(wstr)"<applicationcaption>", 0x00CF0000, 0x00000000, 0x00000000, 0x00000280, 0x000001E0, null, null, kernel32.getModuleHandle(null), cast(ptr)&this ); if(handle is null){ user32.messageBox(null, user32.translateErrorCode(kernel32.getLastError()), cast(wstr)"error", 0x00000000); assert(false, "window creating failed"); } } public void run(){ WINMsg msg; user32.showWindow(handle, 0x0000000A); user32.updateWindow(handle); while(user32.getMessage(cast(ptr)&msg, null, 0, 0)){ user32.translateMessage(cast(ptr)&msg); user32.dispatchMessage(cast(ptr)&msg); } } private dword wndProc(ptr o_hwnd, dword o_msg, dword o_wparam, dword o_lparam){ alias user32.EWindowMessage WM; alias user32.EMouseKey WK; switch(o_msg){ case WM.DESTROY: user32.postQuitMessage(0x00); break; case WM.LBUTTONDOWN: MouseEventArgs l_mea; l_mea.button = MouseButton.LEFT; l_mea.location.x = loword(o_lparam); l_mea.location.x = hiword(o_lparam); user32.messageBox(null, cast(wstr)"LBUTTONDOWN", cast(wstr)"msg", 0x00); // ok it is displayed this.onMouseDown(l_mea); // !!! it is never called break; default: return user32.defWindowProc(o_hwnd, o_msg, o_wparam, o_lparam); } return 0; } public Rect getBounds(){ WINRect l_rc; user32.getWindowRect(this.handle, cast(ptr)&l_rc); with(l_rc) return Rect(left, top, right - left, bottom - top); } } //________________________________________________________ |
October 19, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra |
Zarathustra wrote:
> Function is never called but why?
It shouldn't even COMPILE.
You can't use member functions as Windows callbacks. You haven't even used the correct calling convention on it.
Callbacks for Win API functions have to be, I believe, extern(Windows), and they have to be free functions or static members.
|
October 19, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep Wrote: > It shouldn't even COMPILE. > > You can't use member functions as Windows callbacks. You haven't even used the correct calling convention on it. > > Callbacks for Win API functions have to be, I believe, extern(Windows), and they have to be free functions or static members. My callback wndProc IS static, global function. .wndProc = window.wndProc which is static, and non-member wndClass.wndProc = cast(ptr)&.wndProc; // .wndProc not wndProc pointer to Window object is pass to window.wndProc in additional bytes. My question relates to something completely different. this.onButtonDown(l_mea) // problematic call not return (cast(Window*)user32.getWindowLong(o_hwnd, 0x00)).wndProc(o_hwnd, o_msg, o_wparam, o_lparam);// which works correctly |
October 19, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra | In addition I tested the code in DMD1.050 and DMD2.035. In DMD 1 It works correctly, but in DMD2 line: 'this.onMouseDown(l_mea);' works like 'break' (no exceptions, neither compilation nor linking warnings, just like break). Is it DMD2 bug? |
October 19, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra | Oh, I just find out cause of this behaviour in other module I had: extern (Windows) alias dword function() Tfunc1; extern (Windows) alias dword function(wstr) Tfunc2; const Tfunc2 func2; static this(){ func2 = cast(Tfunc1)0x0; // for DMD2 It is not error!!! // but it doesn't has a sens!!! } |
October 20, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra | Zarathustra Wrote:
> Oh, I just find out cause of this behaviour in other module I had:
> extern (Windows) alias dword function() Tfunc1;
> extern (Windows) alias dword function(wstr) Tfunc2;
> const Tfunc2 func2;
> static this(){
> func2 = cast(Tfunc1)0x0; // for DMD2 It is not error!!!
> // but it doesn't has a sens!!!
> }
looks like a bug
|
October 20, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | Kagamin wrote:
> Zarathustra Wrote:
>
>> Oh, I just find out cause of this behaviour in other module I had:
>> extern (Windows) alias dword function() Tfunc1;
>> extern (Windows) alias dword function(wstr) Tfunc2;
>> const Tfunc2 func2;
>> static this(){
>> func2 = cast(Tfunc1)0x0; // for DMD2 It is not error!!!
>> // but it doesn't has a sens!!!
>> }
>
> looks like a bug
It isn't. Tfunc2 is a function pointer, which is typically the same as size_t. So any int can be stored inside it. It's generally a very bad idea to do so, of course.
|
October 20, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | Don Wrote:
> It isn't. Tfunc2 is a function pointer, which is typically the same as size_t. So any int can be stored inside it. It's generally a very bad idea to do so, of course.
Never mind what is stored inside func2. 0x00 is only to simplify the code.
Tfunc1 - pointer to function without args
Tfunc2 - pointer to function with 1 arg
so:
func2 = cast(Tfunc1)something;
doesn't have a sense, because type of func2 is Tfunc2 type not Tfunc1!
In D1 this causes compilation error, but DMD2.035 doesn't generate any compilation message, even warning.
|
October 20, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zarathustra | On Mon, 19 Oct 2009 02:39:57 -0500, Zarathustra <adam.chrapkowski@gmail.com> wrote: > Function is never called but why? > look at: window.Window.wndProc : case WM.LBUTTONDOWN > //______________________________________________ > module window; > > private import base; > private import structs; > > private static import user32; > private static import kernel32; > private static import gdi32; > > private: > extern (Windows) static dword wndProc(ptr o_hwnd, dword o_msg, dword o_wparam, dword o_lparam){ > > alias user32.EWindowMessage WM; > auto l_wnd = cast(Window*)user32.getWindowLong(o_hwnd, 0x00); > if(o_msg == WM.NCCREATE){ > user32.setWindowLong(o_hwnd, 0x00, *(cast(dword*)o_lparam)); > } > else if(l_wnd is null){ > return 0x00; > } > return (cast(Window*)user32.getWindowLong(o_hwnd, 0x00)).wndProc(o_hwnd, o_msg, o_wparam, o_lparam); > } > > public: > class Window{ > private const ptr handle; > > void onMouseDown(MouseEventArgs o_mea){ > user32.messageBox(null, cast(wstr)"Window", cast(wstr)"msg", 0x00); > } > > this(){ > WINWndClassEx wndClass; > > wndClass.size = 0x00000030; > wndClass.style = 0x00000003; > wndClass.wndProc = cast(ptr)&.wndProc; > wndClass.clsExtraBytes = 0x00000000; > wndClass.wndExtraBytes = 0x00000004; > wndClass.hInstance = kernel32.getModuleHandle(null); > wndClass.hIcon = user32.loadIcon(null, 0x00007F00); > wndClass.hCursor = user32.loadCursor(null, 0x00007F00); > wndClass.hbrBackground = gdi32.getStockObject(0x00000000); > wndClass.menuName = null; > wndClass.className = cast(wstr)"clsname"; > wndClass.hIconSm = user32.loadIcon(null, 0x00007F00); > if(!user32.registerClassEx(cast(ptr)&wndClass)){ > if(kernel32.getLastError() != 0x0582){ > user32.messageBox(null, user32.translateErrorCode(kernel32.getLastError()), cast(wstr)"error", 0x00000000); > assert(false, "window class registering failed"); > } > } > > handle = user32.createWindowEx( > 0, > wndClass.className, > cast(wstr)"<applicationcaption>", > 0x00CF0000, > 0x00000000, > 0x00000000, > 0x00000280, > 0x000001E0, > null, > null, > kernel32.getModuleHandle(null), > cast(ptr)&this > ); > if(handle is null){ > user32.messageBox(null, user32.translateErrorCode(kernel32.getLastError()), cast(wstr)"error", 0x00000000); > assert(false, "window creating failed"); > } > } > > public void run(){ > WINMsg msg; > user32.showWindow(handle, 0x0000000A); > user32.updateWindow(handle); > > while(user32.getMessage(cast(ptr)&msg, null, 0, 0)){ > user32.translateMessage(cast(ptr)&msg); > user32.dispatchMessage(cast(ptr)&msg); > } > } > > private dword wndProc(ptr o_hwnd, dword o_msg, dword o_wparam, dword o_lparam){ > > alias user32.EWindowMessage WM; > alias user32.EMouseKey WK; > > switch(o_msg){ > > case WM.DESTROY: > user32.postQuitMessage(0x00); > break; > > case WM.LBUTTONDOWN: > MouseEventArgs l_mea; > l_mea.button = MouseButton.LEFT; > l_mea.location.x = loword(o_lparam); > l_mea.location.x = hiword(o_lparam); > user32.messageBox(null, cast(wstr)"LBUTTONDOWN", cast(wstr)"msg", 0x00); // ok it is displayed > this.onMouseDown(l_mea); // !!! it is never called > break; > default: return user32.defWindowProc(o_hwnd, o_msg, o_wparam, o_lparam); > } > return 0; > } > > public Rect getBounds(){ > WINRect l_rc; > user32.getWindowRect(this.handle, cast(ptr)&l_rc); > with(l_rc) return Rect(left, top, right - left, bottom - top); > } > } > //________________________________________________________ I don't know what the problem is, but I would try checking to see if the pointer at window construction and the this pointer before calling onMouseDown are the same. Maybe there is a problem with using the result of getWindowLong as a pointer. For example, one value could be 32-bits and the pointer could be 64-bits. I didn't run the code to test anything, I'm just throwing out some ideas which may be way off. -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/ |
October 20, 2009 Re: amazing function behavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Phil Deets | Phil Deets Wrote:
> I don't know what the problem is, but I would try checking to see if the pointer at window construction and the this pointer before calling onMouseDown are the same. Maybe there is a problem with using the result of getWindowLong as a pointer. For example, one value could be 32-bits and the pointer could be 64-bits. I didn't run the code to test anything, I'm just throwing out some ideas which may be way off.
>
> --
Ok I will try to explain:
In my opinion my code should works. I would like to refer to two places in the code.
1. inside window module:
user32.messageBox(null, cast(wstr)"LBUTTONDOWN", cast(wstr)"msg", 0x00);
this.onMouseDown(l_mea);
2: inside test module, version 1:
Window wnd1 = new Window();
wnd1.run()
inside test module, version 2:
Window wnd1 = new Window();
Window wnd2 = new Window();
wnd1.run()
Both versions should work identically. When the mouse button is clicked inside the window, I expect two messageBoxes: The first one with message "LBUTTONDOWN", and the second "Window".
But it is done only with the first version of test module (without wnd2 = new Window()).
In the second case (with wnd2 = new Window()) I see message "LBUTTONDOWN" and Access Violation with DMD 1.050 or just nothing! with DMD 2.035 (therefore 'amazing' in the topic).
I apologize for my horrible English, but I hope I explained that enough clearly.
|
Copyright © 1999-2021 by the D Language Foundation