Ok, so i am trying to do something as simple as changing the background color of the window when the mouse is over it. I have tried so many things, most of them in comment and none of them worked:

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#include <Windows.h>

LRESULT CALLBACK WindowProcedure
(
HWND WindowHandle,
UINT Message,
WPARAM WordParameter,
LPARAM LongParameter
)
{
PAINTSTRUCT PaintStructure;
HDC DeviceContextHandle;
TRACKMOUSEEVENT MouseEvent;
RECT Rectangle;

switch(Message)
{
case WM_ERASEBKGND:
//SetClassLongPtr(WindowHandle, GCLP_HBRBACKGROUND, RGB(0,0,0));
break;
case WM_MOUSEHOVER:
//GetWindowRect(WindowHandle, &Rectangle);
//RedrawWindow(WindowHandle, &Rectangle, NULL, RDW_UPDATENOW);
//PostMessage(WindowHandle, WM_PAINT, 200, NULL);
break;
case WM_MOUSEMOVE:
MouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
MouseEvent.dwFlags = TME_HOVER;
MouseEvent.dwHoverTime = 100;
MouseEvent.hwndTrack = WindowHandle;
TrackMouseEvent(&MouseEvent);
break;
case WM_PAINT:
/*if (WordParameter == 200) {
DeviceContextHandle = GetDC(WindowHandle);
SetBkColor(DeviceContextHandle, RGB(0,0,0));
}*/
DeviceContextHandle = BeginPaint(WindowHandle, &PaintStructure);
//SetBkColor(DeviceContextHandle, RGB(0,0,0));
EndPaint(WindowHandle, &PaintStructure);
break;
case WM_DESTROY:
PostQuitMessage(WM_QUIT);
break;
default:
return DefWindowProc(WindowHandle, Message, WordParameter, LongParameter);
}
return 0;
}

int WINAPI wWinMain
(
HINSTANCE CurrentInstance,
HINSTANCE PreviousInstance,
LPWSTR CommandLine,
int CommandShow
)
{
WNDCLASSEX WindowClass = {0};
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
WindowClass.lpfnWndProc = WindowProcedure;
WindowClass.cbClsExtra = NULL;
WindowClass.cbWndExtra = NULL;
WindowClass.hInstance = CurrentInstance;
WindowClass.hIcon = NULL;
WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WindowClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
WindowClass.lpszMenuName = NULL;
WindowClass.lpszClassName = "Main Class";
WindowClass.hIcon = NULL;
RegisterClassEx(&WindowClass);

RECT Rectangle = {0, 0, 640, 480};
AdjustWindowRect(&Rectangle, WS_OVERLAPPEDWINDOW, FALSE);

HWND WindowHandle = CreateWindowEx
(
WS_EX_CONTEXTHELP,
"Main Class",
"Window Title",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
Rectangle.right - Rectangle.left,
Rectangle.bottom - Rectangle.top,
NULL,
NULL,
CurrentInstance,
NULL
);

ShowWindow(WindowHandle, CommandShow);
UpdateWindow(WindowHandle);

MSG Message = {0};
while(Message.message != WM_QUIT)
{
if (PeekMessage(&Message, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}

return (int)Message.wParam;
}


-I tried to Send/PostMessage back to WM_PAINT and change the background color.
-I tried using SetClassLongPtr() which worked but it did not update the Window automatically. I had to resize/minimize/restore window for it to show the effects.
-Most of the forums say to use WM_ERASEBKGND but doesn't say how specifically. Therefore i can't get it working neither.

I tried so many combinations with no luck so i need help.  :sad:
Posted on 2012-04-05 18:34:27 by banzemanga

-I tried using SetClassLongPtr() which worked but it did not update the Window automatically. I had to resize/minimize/restore window for it to show the effects.


I think you should do SetClassLongPtr(), followed by an InvalidateRect(hWnd, NULL) to force a redraw of your window (resizing/minimizing etc would also trigger an InvalidateRect()).
Posted on 2012-04-06 05:13:19 by Scali
Thanks Scali. InvalidateRect() is some weird name for a function that updates the Window. I thought that i had to use UpdateWindow() or RedrawWindow() in some weird way; which did not work by the way.

I have a questions about custom controls. I found out that the way Window creates default controls is by creating child-windows with predetermined properties. And this goes for Buttons, text-boxes, combo-boxes, text-labels, etc. So any custom control for the GUI that i would like to make i would probably have to draw the images and them paste them on top of child windows and have them react to different messages.

1) Does it mean that for every button i make i would have to make a child window and attach a callback function for each of them?
2) What about when making game menus and stuff? Are those also child Windows?
Posted on 2012-04-06 17:51:56 by banzemanga

Thanks Scali. InvalidateRect() is some weird name for a function that updates the Window. I thought that i had to use UpdateWindow() or RedrawWindow() in some weird way; which did not work by the way.


Well, technically it's not a function that updates a window.
You'll have to know a bit about the basics of the GUI for it to make sense.
Windows did not support any kind of backbuffering, historically (memory was expensive in the olden days). So what it does instead, is to redraw windows on-the-fly. When Windows overlap on screen, it marks the overlapping parts with rectangles (in general, windows are rectangular in shape).
Parts of a window that need to be redrawn are 'invalidated' (marked 'dirty') by the system. This results in new WM_PAINT messages being sent to the window (including the actual rectangle that needs to be redrawn). There is also a ValidateRect() function that marks a rectangle as 'clean' again.

So that's pretty much how Windows works: something happens that marks (part of) your window as 'dirty'/invalidated, then your window redraws it and marks it validated again. Lather, rinse, repeat.
(Since Vista/Aero, things don't work entirely like this anymore. Because the whole UI is now drawn with the GPU, each window gets its own backbuffer as a texture in videomemory. As a result, overlapping windows don't physically draw on top of eachother anymore. The GPU just renders each window using the z-buffer, but the actual textures containing the window contents are unaffected by the overlapping. This also means that in Aero-mode, you get a lot less invalidate/validate action).

By calling InvalidateRect() yourself, you can mark a region of a window for redrawing. Passing NULL instead of an actual rectangle means that the entire window needs to be redrawn.
Posted on 2012-04-07 04:54:23 by Scali