Re: WindowProc in a class - function and pointer problem

2013-05-23 Thread evilrat

On Thursday, 23 May 2013 at 06:31:02 UTC, Sean Cavanaugh wrote:


I had a partial port of WTL over to D which worked well enough 
for what I needed, the core of the WndProc handling is down 
below.   Each HWND is owned by the thread it was created on, so 
assigning it into D associative array (which is thread local) 
can do the trick.  It involved a hack, before any call to the 
Win32 CreateWindow/CreateWindowEx APIs, to capture the 
association with the new HWND and to remove them when they get 
cleaned up.  There is probably a better way but this worked 
enough to get started, and should work with multiple windows 
reasonably well.




sure this is doable but it breaks the entire idea of oop. this is 
also can be put as static member, still it would break oop.


that link i put here is show what is really needed, and it's 
clean and simple.


simply there is only 2 required methods, one for creating(and 
binding) hwnd with class instance and another to retrieve that 
instance and do its own message handling, no other code necessary 
and everything incapsulated. but i don't remember if it works 
without gc messed up that instance while not falling to such 
tricks like arrays(because it is may be possible that gc collect 
instance while window is alive).


Re: WindowProc in a class - function and pointer problem

2013-05-22 Thread Sean Cavanaugh

On 5/22/2013 8:49 PM, evilrat wrote:

On Wednesday, 22 May 2013 at 21:42:32 UTC, D-sturbed wrote:


Yes I'm in the "multiple Window case", every window is wraped in a
class and has its own message handler. I know that Win, in its
callback system, often lets you retrieve a pointer to something, and I
haven't get it was possible in this case...(which is you seem to
describe). I will try this tomorrow.


you can't really make it without static wndproc. if you don't know how
to do it just go google some wndproc in a class tutors for c++, i can
even recommend you one(i had used my own port of this in D before i
switched to crossplatform lib for my needs) -
http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx



I had a partial port of WTL over to D which worked well enough for what 
I needed, the core of the WndProc handling is down below.   Each HWND is 
owned by the thread it was created on, so assigning it into D 
associative array (which is thread local) can do the trick.  It involved 
a hack, before any call to the Win32 CreateWindow/CreateWindowEx APIs, 
to capture the association with the new HWND and to remove them when 
they get cleaned up.  There is probably a better way but this worked 
enough to get started, and should work with multiple windows reasonably 
well.







CWindowInterface g_CreatingWindow;
CWindowInterface[HWND] g_HWNDtoObject;


extern (Windows)
int CWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int WindowProcReturnValue = 0;

/*
auto EventMsg = appender!string();
formattedWrite(EventMsg, "EventMsg (hWnd=%1$s) (uMsg=%2$s) 
(wParam=%3$s) (lParam=%4$s)\n", cast(DWORD)hWnd, cast(DWORD)uMsg, 
cast(DWORD)wParam, cast(DWORD)lParam);

OutputDebugString(toUTFz!(const(wchar)*)(EventMsg.data));
*/

if (g_CreatingWindow)
{
g_HWNDtoObject[hWnd] = g_CreatingWindow;
g_CreatingWindow = null;
}
auto Window = g_HWNDtoObject[cast(HANDLE)hWnd];
if (Window is null)
{
WindowProcReturnValue = DefWindowProc(hWnd, uMsg, wParam, lParam);
}
else
{
WindowProcReturnValue = Window.WindowProc(hWnd, uMsg, wParam, 
lParam);

}
if (uMsg == WM_NCDESTROY)
{
g_HWNDtoObject.remove(hWnd);
}
return WindowProcReturnValue;
}



Re: WindowProc in a class - function and pointer problem

2013-05-22 Thread evilrat

On Wednesday, 22 May 2013 at 21:42:32 UTC, D-sturbed wrote:


Yes I'm in the "multiple Window case", every window is wraped 
in a class and has its own message handler. I know that Win, in 
its callback system, often lets you retrieve a pointer to 
something, and I haven't get it was possible in this 
case...(which is you seem to describe). I will try this 
tomorrow.


you can't really make it without static wndproc. if you don't 
know how to do it just go google some wndproc in a class tutors 
for c++, i can even recommend you one(i had used my own port of 
this in D before i switched to crossplatform lib for my needs) - 
http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx


Re: WindowProc in a class - function and pointer problem

2013-05-22 Thread D-sturbed

On Wednesday, 22 May 2013 at 21:22:52 UTC, Diggory wrote:

On Wednesday, 22 May 2013 at 20:25:40 UTC, Simen Kjaeraas wrote:

On 2013-05-22, 21:30, D-sturbed wrote:

Hello, is there a way to wrap a WindowProc (so "LRESULT 
WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM 
lParam) nothrow") in a class and to link it to a WindowClass 
without puting it as "static" ?


Because defacto every datum used in the WindowProc must also 
be static.
The problem technically is that if "static" is not specified, 
the compiler won't allow this: "MyWinClass.lpfnWndProc = 
&TheWindowProcInMyClass".


I've also tried this: "MyWinClass.lpfnWndProc = 
(&TheWindowProcInMyClass).funcptr" but, while it compiles, it 
drastically fails at the run-time...


Not possible, no. What you *can* do is have some way to 
translate from
hwnd to class instance, and fetch the right instance inside 
the static

wndProc to call a member function on that.


If you are only going to have one window you can store the 
"this" pointer in a global variable.


If you want to have multiple windows each with messages going 
to an instance of a class, you need to do the following:
- Specify the "this" pointer as the lpParam argument to 
CreateWindow

- Hook up a static WndProc function
- Have the static function handle a WM_NCCREATE message as 
follows:
- Cast the "lParam" parameter to a CREATESTRUCT* and 
retrieve the "this" pointer from the "lpCreateParams" member.
- Use "SetWindowLongPtr" to set the GWLP_USERDATA property 
of the window "hwnd" to the "this" pointer

- Have the static function handle all messages as follows:
- Use "GetWindowLongPtr" to get the GWLP_USERDATA property 
of the window "hwnd" to get the "this" pointer
- Pass the message on to a non-static WndProc in the class 
using the discovered "this" pointer


You also need to make sure that there is a separate reference 
to the class instance for as long as the window exists, because 
the garbage collector will not scan the window properties and 
so may think the object is garbage otherwise.


Yes I'm in the "multiple Window case", every window is wraped in 
a class and has its own message handler. I know that Win, in its 
callback system, often lets you retrieve a pointer to something, 
and I haven't get it was possible in this case...(which is you 
seem to describe). I will try this tomorrow.




Re: WindowProc in a class - function and pointer problem

2013-05-22 Thread Diggory

On Wednesday, 22 May 2013 at 20:25:40 UTC, Simen Kjaeraas wrote:

On 2013-05-22, 21:30, D-sturbed wrote:

Hello, is there a way to wrap a WindowProc (so "LRESULT 
WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM 
lParam) nothrow") in a class and to link it to a WindowClass 
without puting it as "static" ?


Because defacto every datum used in the WindowProc must also 
be static.
The problem technically is that if "static" is not specified, 
the compiler won't allow this: "MyWinClass.lpfnWndProc = 
&TheWindowProcInMyClass".


I've also tried this: "MyWinClass.lpfnWndProc = 
(&TheWindowProcInMyClass).funcptr" but, while it compiles, it 
drastically fails at the run-time...


Not possible, no. What you *can* do is have some way to 
translate from
hwnd to class instance, and fetch the right instance inside the 
static

wndProc to call a member function on that.


If you are only going to have one window you can store the "this" 
pointer in a global variable.


If you want to have multiple windows each with messages going to 
an instance of a class, you need to do the following:
- Specify the "this" pointer as the lpParam argument to 
CreateWindow

- Hook up a static WndProc function
- Have the static function handle a WM_NCCREATE message as 
follows:
- Cast the "lParam" parameter to a CREATESTRUCT* and retrieve 
the "this" pointer from the "lpCreateParams" member.
- Use "SetWindowLongPtr" to set the GWLP_USERDATA property of 
the window "hwnd" to the "this" pointer

- Have the static function handle all messages as follows:
- Use "GetWindowLongPtr" to get the GWLP_USERDATA property of 
the window "hwnd" to get the "this" pointer
- Pass the message on to a non-static WndProc in the class 
using the discovered "this" pointer


You also need to make sure that there is a separate reference to 
the class instance for as long as the window exists, because the 
garbage collector will not scan the window properties and so may 
think the object is garbage otherwise.


Re: WindowProc in a class - function and pointer problem

2013-05-22 Thread Simen Kjaeraas

On 2013-05-22, 21:30, D-sturbed wrote:

Hello, is there a way to wrap a WindowProc (so "LRESULT WindowProc(HWND  
hWnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow") in a class  
and to link it to a WindowClass without puting it as "static" ?


Because defacto every datum used in the WindowProc must also be static.
The problem technically is that if "static" is not specified, the  
compiler won't allow this: "MyWinClass.lpfnWndProc =  
&TheWindowProcInMyClass".


I've also tried this: "MyWinClass.lpfnWndProc =  
(&TheWindowProcInMyClass).funcptr" but, while it compiles, it  
drastically fails at the run-time...


Not possible, no. What you *can* do is have some way to translate from
hwnd to class instance, and fetch the right instance inside the static
wndProc to call a member function on that.

--
Simen