Currently I'm developing fully transparent windows controls. And what
should I say, I really did it (some people said that it isn't
possible?!?).
I only have got a *last* little problem:
For example I use my own (transparent) component and a windows
standard component. Now I need to know when the windows standard
component (a button for example) receives a WM_PAINT message. Because
I want to redraw my transparent window after the button was repainted.
I thought that this is no problem. I already have some SetWindowHookEx
experiences, so I thought capturing the WM_PAINT message should do it.
But WH_CALLWNDPROC *NEVER* gets the WM_PAINT message on my system!
WH_CALLWNDPROCRET does not, too!
Upfmh?? I read in the newsgroups that it is possible to receive
WM_PAINT with hooks? But how?
------------------
My code:
function PaintHookPreProc(nCode: Integer; wParam: WPARAM; lParam:
LPARAM): LRESULT; stdcall;
var
CWP: PCWPSTRUCT;
begin
Result := CallNextHookEx(GPaintHookPre, nCode, wParam, lParam);
if (nCode = HC_ACTION) then
begin
CWP := PCWPSTRUCT(lParam);
if (CWP.message = WM_PAINT) then
begin
// Debugger never gets in
end;
if (CWP.message = WM_NCPAINT) then
begin
// Debugger gets in
end;
end;
end;
[...]
GPaintHookPre := SetWindowsHookEx(WH_CALLWNDPROC, @PaintHookPreProc,
hInstance, GetCurrentThreadId);
----------
BTW: I'm using WinXP and Delphi!
Thanks,
Kirsten
WM_PAINT is retrieved with a WH_GETMESSAGE hook.
--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)
Well, this helps finding a solution. The only thing is:
The GetMsgProc hook procedure:
---------------------------------
"Before passing the retrieved message to the destination window procedure, the system passes the message to the hook procedure"
Unfortunatelly I need to do something after WM_PAINT! Suggestions?
One technique would be to subclass any window procedure that gets a WM_PAINT
message. Less intrusive (but possibly less effective, depending on what you
are doing), would be to register a user defined message with the system
(using RegisterWindowMessage) and then have your hook procedure post it to
the relevant window whenever the hook intercepts a WM_PAINT message. The
posted message will be retrieved by the window after it has processed
WM_PAINT. When this happens, the message will be passed to your hook and you
can take this as the cue to do your own painting.
Subclassing? You mean that I override the WndProc? Well, I tried it the following way:
Create a CBT hook to intercept window creation...
Then I used SetWindowLong and GetWindowLong to override the WndProc...
In my new WndProc I asked if message is WM_PAINT...
But what should I say, nobody would believe me! I haven't got any WM_PAINT message in my overriden WndProc!
I know it is absurd, because I use this technique to override the WM_PAINT of a normal top level window, for example?!?
BTW: In "my" WndProc I get everything: WM_ERASEBACKGROUND, WM_NCPAINT,... but NO WM_PAINT. I have no answer to this!
Yes, substitute your own window procedure (which will call the default
window procedure for most if not all messages). Personally, I would have
first tried the other approach I suggested.
> Well, I tried it
> the following way:
>
> Create a CBT hook to intercept window creation...
>
> Then I used SetWindowLong and GetWindowLong to override the WndProc...
I presume that you are using GetWindowLong to retrieve the default window
procedure (I always get it from the return value of SetWindowLong).
> In my new WndProc I asked if message is WM_PAINT...
>
> But what should I say, nobody would believe me! I haven't got any
> WM_PAINT message in my overriden WndProc!
>
> I know it is absurd, because I use this technique to override the
> WM_PAINT of a normal top level window, for example?!?
>
> BTW: In "my" WndProc I get everything: WM_ERASEBACKGROUND,
> WM_NCPAINT,... but NO WM_PAINT. I have no answer to this!
I guess there are two possibilities:
1. This is a strange window that doesn't receive WM_PAINT messages (such
windows are possible).
2. You are doing something wrong.
As for 1., VC++ comes with a program call Spy++ which enables you to monitor
messages for a window. I don't know if your Delphi setup has anything
similar. If not, you can download this program for free:
(I suggest you test the window WITHOUT your subclassing window procedure.)
As for 2., I couldn't comment without seeing your code.
Since it is Delphi, I still might not have anything useful to say but, if
not, someone else may.
The code hasn't existed more than 10 hours, so I cannot post it. Of
course an error could be in there, but I have seen over it about 20
times and I'm really used to subclassing. (Yes, I use it the way you
described).
BTW, I'm using Winspector Spy, and my window gets WM_PAINT normally.
When I override it in Delphi the normal way, it works, too! Well, as I
said, very strange. But I have a similar problem with a WM_COMMAND in
Delphi, which isn't sent in design time but in runtime. Perhaps Delphi
really mixes something up.
If anyone has suggestions or answers, please posts!
Thanks,
Kirsten