www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.dwt - Binding win32 window to a D class

reply Serg Kovrov <kovrov no.spam> writes:
Hello All,

This one should be beaten to death already, but still I do not aware of 
fast/elegant way.

Maybe we could collect all possible solutions on that matter for D in 
one place. Starting in this thread and hopefully move to a wiki page.

As I understand for D there even less available techniques then for C++. 
In case of C++ I am aware of following:

1. using static method as window procedure and store pointer to class 
instance in with SetWindowLongPtr. when dispatching messages retrieve 
pointer to class with GetWindowLongPtr and call class method. This can't 
be used in D since our pointer might become invalid as GC could swap / 
compact memory. This is covered in "Garbage Collection" article - 
http://digitalmars.com/d/garbage.html

2. Same as above, but stores class reference in static array/hash and 
used SetWindowLongPtr/GetWindowLongPtr to store index to retrieve class 
from that static array. This actually works for D. But it is most slow 
technique since there we need to call GetWindowLongPtr and lookup for 
class pointer/reference on every windows message.

3. So called thunking. A hack to store pointer to class method in 
WNDCLASS.lpfnWndProc. Uses inline assembler substitute addresses at 
runtime. Should be faster than other techniques since there is no need 
to constantly call GetWindowLongPtr. Used in ATL/WTL. Could not be used 
in D for same reason as first solution.

Thats seems all. The only available solution (from listed above) for D 
is #2.

I hope there is other methods to solve this problem, and perhaps there 
are completely different approaches to organize win32 window management, 
and I'd like to discuss them here.

Thanks
--
serg.
Aug 09 2006
next sibling parent Derek Parnell <derek psyc.ward> writes:
On Wed, 09 Aug 2006 16:34:44 +0300, Serg Kovrov wrote:

 Hello All,
 
 This one should be beaten to death already, but still I do not aware of 
 fast/elegant way.

 2. Same as above, but stores class reference in static array/hash and 
 used SetWindowLongPtr/GetWindowLongPtr to store index to retrieve class 
 from that static array. This actually works for D. But it is most slow 
 technique since there we need to call GetWindowLongPtr and lookup for 
 class pointer/reference on every windows message.

I use this method in an interpreted language with no perceived slowness. Ok, so it might be slower than other methods but under no meaningful sense is it actually slow. -- Derek Parnell Melbourne, Australia "Down with mediocrity!"
Aug 09 2006
prev sibling parent reply freeagle <freeagle inmail.sk> writes:
Serg Kovrov wrote:
 Hello All,
 
 This one should be beaten to death already, but still I do not aware of 
 fast/elegant way.
 
 Maybe we could collect all possible solutions on that matter for D in 
 one place. Starting in this thread and hopefully move to a wiki page.
 
 As I understand for D there even less available techniques then for C++. 
 In case of C++ I am aware of following:
 
 1. using static method as window procedure and store pointer to class 
 instance in with SetWindowLongPtr. when dispatching messages retrieve 
 pointer to class with GetWindowLongPtr and call class method. This can't 
 be used in D since our pointer might become invalid as GC could swap / 
 compact memory. This is covered in "Garbage Collection" article - 
 http://digitalmars.com/d/garbage.html
 
 2. Same as above, but stores class reference in static array/hash and 
 used SetWindowLongPtr/GetWindowLongPtr to store index to retrieve class 
 from that static array. This actually works for D. But it is most slow 
 technique since there we need to call GetWindowLongPtr and lookup for 
 class pointer/reference on every windows message.
 
 3. So called thunking. A hack to store pointer to class method in 
 WNDCLASS.lpfnWndProc. Uses inline assembler substitute addresses at 
 runtime. Should be faster than other techniques since there is no need 
 to constantly call GetWindowLongPtr. Used in ATL/WTL. Could not be used 
 in D for same reason as first solution.
 
 Thats seems all. The only available solution (from listed above) for D 
 is #2.
 
 I hope there is other methods to solve this problem, and perhaps there 
 are completely different approaches to organize win32 window management, 
 and I'd like to discuss them here.
 
 Thanks
 -- 
 serg.

the second approach, without the need for get/setPtr: class Windows { static Window[HWND] _windows; . . . int windowProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam) { . . . } } extern(Windows) int wndProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam) { Window* wnd = hwnd in Window._windows; if(wnd !is null) { return wnd.windowProc(hwnd, message, wParam, lParam); } else { return DefWindowProc(hwnd, message, wParam, lParam); } }
Sep 09 2006
next sibling parent freeagle <freeagle inmail.sk> writes:
freeagle wrote:
 Serg Kovrov wrote:
 Hello All,

 This one should be beaten to death already, but still I do not aware 
 of fast/elegant way.

 Maybe we could collect all possible solutions on that matter for D in 
 one place. Starting in this thread and hopefully move to a wiki page.

 As I understand for D there even less available techniques then for 
 C++. In case of C++ I am aware of following:

 1. using static method as window procedure and store pointer to class 
 instance in with SetWindowLongPtr. when dispatching messages retrieve 
 pointer to class with GetWindowLongPtr and call class method. This 
 can't be used in D since our pointer might become invalid as GC could 
 swap / compact memory. This is covered in "Garbage Collection" article 
 - http://digitalmars.com/d/garbage.html

 2. Same as above, but stores class reference in static array/hash and 
 used SetWindowLongPtr/GetWindowLongPtr to store index to retrieve 
 class from that static array. This actually works for D. But it is 
 most slow technique since there we need to call GetWindowLongPtr and 
 lookup for class pointer/reference on every windows message.

 3. So called thunking. A hack to store pointer to class method in 
 WNDCLASS.lpfnWndProc. Uses inline assembler substitute addresses at 
 runtime. Should be faster than other techniques since there is no need 
 to constantly call GetWindowLongPtr. Used in ATL/WTL. Could not be 
 used in D for same reason as first solution.

 Thats seems all. The only available solution (from listed above) for D 
 is #2.

 I hope there is other methods to solve this problem, and perhaps there 
 are completely different approaches to organize win32 window 
 management, and I'd like to discuss them here.

 Thanks
 -- 
 serg.

the second approach, without the need for get/setPtr: class Windows { static Window[HWND] _windows; . . . int windowProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam) { . . . } } extern(Windows) int wndProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam) { Window* wnd = hwnd in Window._windows; if(wnd !is null) { return wnd.windowProc(hwnd, message, wParam, lParam); } else { return DefWindowProc(hwnd, message, wParam, lParam); } }

sry, class Window, not Windows, typo
Sep 09 2006
prev sibling next sibling parent reply Serg Kovrov <kovrov no.spam> writes:
freeagle wrote:
 the second approach, without the need for get/setPtr:

Thanks for replay freeagle. Actually, yes. I currently use this very same approach. This is similar to MFC's design - to store window objects in global handle map. It's amazing how easy is to implement this in D using standard language facilities with just few lines of code. -- serg.
Sep 09 2006
parent freeagle <freeagle inmail.sk> writes:
Serg Kovrov wrote:
 freeagle wrote:
 the second approach, without the need for get/setPtr:

Thanks for replay freeagle. Actually, yes. I currently use this very same approach. This is similar to MFC's design - to store window objects in global handle map. It's amazing how easy is to implement this in D using standard language facilities with just few lines of code.

that's why we love this language ;)
Sep 10 2006
prev sibling parent Dune <not.yet yahoo.com> writes:
== Quote from freeagle (freeagle inmail.sk)'s article
 the second approach, without the need for get/setPtr:
 class Windows
 {
 	static Window[HWND] _windows;
 	.
 	.
 	.
 	int windowProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam)
 	{
 		.
 		.
 		.
 	}
 }
 extern(Windows)
 int
 wndProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam)
 {
 	Window* wnd = hwnd in Window._windows;
 	if(wnd !is null)
 	{
 		return wnd.windowProc(hwnd, message, wParam, lParam);
 	}
 	else
 	{
 		return DefWindowProc(hwnd, message, wParam, lParam);
 	}
 }

This looks pretty simple even for a newbie like me, but somehow I can't associate the following line in wndProc: Window* wnd = hwnd in Window._windows; to the class... Inside the class I'm using the CreateWindowA WinAPI, which returns the needed HWND, but how do I put this HWND into the _windows array? Is there a chance to get a minimalistic but full working example? Also somehow the compiler (GDC) always wants 'main' but afaik in gui apps it should be 'winmain'... Thanks says a newbie (to D...) Dune
Dec 26 2006