Thread overview
Binding win32 window to a D class
Aug 09, 2006
Serg Kovrov
Aug 09, 2006
Derek Parnell
Sep 09, 2006
freeagle
Sep 09, 2006
freeagle
Sep 09, 2006
Serg Kovrov
Sep 10, 2006
freeagle
Dec 26, 2006
Dune
August 09, 2006
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.
August 09, 2006
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!"
September 09, 2006
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);
	}
}
September 09, 2006
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
September 09, 2006
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.
September 10, 2006
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 ;)
December 26, 2006
== 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