I have subclassed some of the button controls, as I myself draw the entire user interface (in the hdc dialog box). This is done in order to avoid flickering, the goal is that all drawings are executed through a single memDC - preventing the user interface from being updated stepwise.
So, I draw everything against the background of the dialog, then place some buttons above the areas of the user interface that should respond to mouse events. So far, so good. Or so I thought.
I subclassed the buttons using the following WndProc, expecting Windows to do everything as usual except for the drawing.
LRESULT CALLBACK invisibleBtnProc(HWND hwndBtn, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
long oldProc = GetWindowLong(hwndBtn, GWL_USERDATA);
switch (uMsg)
{
case WM_PAINT:
ValidateRect(hwndBtn, NULL);
return 0;
case WM_ERASEBKGND:
return 1;
}
return CallWindowProc((WNDPROC)oldProc, hwndBtn, uMsg, wParam, lParam);
}
Buttons are created and subclassed by the following code:
for (i=0; i<n; i++)
{
btn = CreateWindow(WC_BUTTON, L"", WS_VISIBLE|WS_CHILD, 0,0,0,0, hwndDlg, (HMENU)(firstBigBtnId+i), hInst, NULL);
long btnProcCur = GetWindowLong(btn, GWL_WNDPROC);
SetWindowLong(btn, GWL_USERDATA, btnProcCur);
SetWindowLong(btn, GWL_WNDPROC, (long) invisibleBtnProc);
}
MinGW Code:: Blocks, . ( , )
, MSVC VS2010 . , - . , , 'button'.
WMF (emf? ), - , , , , -.
:

, , , - , . .
- ( , InvalidateRect ) . .
, ?
EDIT: SCCCE ( GCC, )
#include <windows.h>
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
RECT btnRect;
const int btnSize = 150;
const int btnId = 1000;
HINSTANCE hInst;
char szClassName[ ] = "CodeBlocksWindowsApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
HWND hwnd;
MSG messages;
WNDCLASSEX wincl;
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return 0;
hwnd = CreateWindowEx (
0,
szClassName,
"Code::Blocks Template Windows App",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
544,
375,
HWND_DESKTOP,
NULL,
hThisInstance,
NULL
);
ShowWindow (hwnd, nCmdShow);
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
LRESULT CALLBACK invisibleBtnProc(HWND hwndBtn, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
long oldProc = GetWindowLong(hwndBtn, GWL_USERDATA);
switch (uMsg)
{
case WM_PAINT:
ValidateRect(hwndBtn, NULL);
return 0;
case WM_ERASEBKGND:
return 1;
}
return CallWindowProc((WNDPROC)oldProc, hwndBtn, uMsg, wParam, lParam);
}
void onSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
RECT mRect;
GetClientRect(hwnd, &mRect);
btnRect.left = (mRect.right - btnSize) / 2;
btnRect.top = (mRect.bottom - btnSize) / 2;
btnRect.right = btnRect.left + btnSize;
btnRect.bottom = btnRect.top + btnSize;
HWND btn;
btn = GetDlgItem(hwnd, btnId);
MoveWindow(btn, btnRect.left, btnRect.top, btnSize, btnSize, false);
InvalidateRect(hwnd, NULL, false);
}
void onPaint(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH bkBrush, redBrush;
RECT mRect;
GetClientRect(hwnd, &mRect);
hdc = BeginPaint(hwnd, &ps);
bkBrush = CreateSolidBrush(RGB(51,51,51) );
redBrush = CreateSolidBrush(RGB(255,0,0) );
FillRect(hdc, &mRect, bkBrush);
FillRect(hdc, &btnRect, redBrush);
DeleteObject(bkBrush);
DeleteObject(redBrush);
EndPaint(hwnd, &ps);
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
HWND tmp;
tmp = CreateWindow("Button", "Press Me", WS_VISIBLE|WS_CHILD, 0,0,0,0, hwnd, (HMENU)btnId, hInst, NULL);
long oldProc;
oldProc = GetWindowLong(tmp, GWL_WNDPROC);
SetWindowLong(tmp, GWL_USERDATA, oldProc);
SetWindowLong(tmp, GWL_WNDPROC, (long)invisibleBtnProc);
return 0;
case WM_DESTROY:
PostQuitMessage (0);
break;
case WM_SIZE:
onSize(hwnd, wParam, lParam);
return 0;
case WM_PAINT:
onPaint(hwnd, wParam, lParam);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case btnId:
MessageBeep(MB_ICONEXCLAMATION);
break;
}
return 0;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}