Click to See Complete Forum and Search --> : SetWindowRgn change behaviour of WM_LBUTTONDOWN


ckkwil
January 25th, 2006, 06:43 AM
Dear Sir/Madame,

I am writing an irregular button by creating a skin button class using Win32 API, but it does not work correctly after setting SetWindowRgn.
My procedures are:

In Constructor:
1) Make an irregular region and load the "button up/down" bitmaps.

2) hButtonWnd=CreateWindowEx(0 ,"BUTTON" ,NULL,WS_CHILD |WS_VISIBLE |BS_OWNERDRAW ,x, y, m_iWidth, m_iHeight, mhwnd, (HMENU)idc_const, g_hInst, NULL); //the bitmap size must be within (80,80).
...

3) Subclass the window procedure
m_OldWndProc = (WNDPROC)SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)SkinButtonWndProc);
...

4) Set the region
SetWindowRgn(m_hWnd, m_rgnSkin, true);

In SkinButtonWndProc:
5) WM_LBUTTONDOWN:
Set a flag to indicate the button is pressed down, and it will be used for displaying a "button down " bitmap.
InvalidateRgn(hWnd, pSkin->m_rgnSkin, TRUE);

6) WM_LBUTTONUP:
Set a flag to indicate the button is released, and it will be used for displaying a "button up" bitmap.
InvalidateRgn(hWnd, pSkin->m_rgnSkin, TRUE);

7) WM_PAINT:
I will draw the button bitmap("button up" or "button down") by BitBlt() according to the flag.

This cannot work normally, if I move the mouse over the skin button, and presses the button, it will not have the correct action with the button immediately, but after I release the mouse button, then the action starts. I have checked it in debug mode, and run it step by step, it seems that after setting the SetWindowRgn(), when I click the mouse button, it will generate WM_LBUTTONDOWN and also a WM_LBUTTONUP message, so the bitmap shown is always the "button up" bitmap

But after removing the SetWindowRgn in step #4, then it works normally.
Could anyone know what's wrong with my code?
Where should I set SetWindowRgn() and any code is missed?

Thanks in advance!

ckkwil

kirants
January 25th, 2006, 09:22 AM
Is it possible for you to upload a sample project that exhibits this behavior ? In such situations, normally examining the code will help rather than ask questions back and forth. Also, it is much easier for people to jump in when they have the code ready instead of having to code to replicate your problem..

ckkwil
January 25th, 2006, 10:49 PM
Hi,

I know the problem now, it is because the "pSkin->m_rgnSkin" is not valid after calling the SetWindowRgn(), (in MSDN it said that user should not make any further function calls with this region handle)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_2him.asp

Hence using an invalid region leading to strange behaviour.
Now I solve it by making a copy of the irregular region
"m_rgnSkinCopy" in step #1. Hence one is used for SetWindowRgn() and the copy is used in other function call.

Then in step #5,6,7 I use "m_rgnSkinCopy" instead of "m_rgnSkin".

ie,
In SkinButtonWndProc:
5) WM_LBUTTONDOWN:
Set a flag to indicate the button is pressed down, and it will be used for displaying a "button down " bitmap.
InvalidateRgn(hWnd, pSkin->m_rgnSkinCopy, TRUE);

6) WM_LBUTTONUP:
Set a flag to indicate the button is released, and it will be used for displaying a "button up" bitmap.
InvalidateRgn(hWnd, pSkin->m_rgnSkinCopy, TRUE);

7) WM_PAINT:
HDC hdc=BeginPaint(hWnd,&ps);
SelectClipRgn(ps.hdc, pSkin->m_rgnSkinCopy);
::BitBlt(ps.hdc, 0, 0, 50, 50, pSkin->HDC(), 0, 0, SRCCOPY);
EndPaint(hWnd,&ps);

where the HDC() is to return the related DC according to the button flag,
HDC CSkinButton::HDC()
{
if (b_buttonDown){
return m_dcSkinDown;
}
else{
return m_dcSkin;
}
}

Pls feel free to give comment to my solution, thanks!
(Sorry for not uploading the whole project, since it is too large.)