Here is my code. I'm trying to create an edit control. It's not showing, however. Can some take a look at my code and point out the errors please. I can't figure out where the error is. I feel It might have something to do with the parent child relationship.
#include <cstdlib>
#include <windows.h>
#define MAINWINDOW_CLASS_ID 140;
const char* MAINWINDOW_CLASS_NAME = "Main Window";
const char* TEXTAREA_CLASS_NAME = "EDIT";
using namespace std;
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam);
/*
* Initialize the window class and register it.
*/
BOOL initInstance(HINSTANCE hInstance);
/*
* Create and show the window
*/
HWND initWindow(HINSTANCE hInstance);
HWND createTextArea(HWND hParent);
/*
*
*/
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevInstance, LPSTR lpCmdline, INT cmdlShow)
{
if (!initInstance(hInstance))
return 0;
HWND hwndMain = initWindow(hInstance);
ShowWindow(hwndMain, cmdlShow);
MSG msg = {} ;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
BOOL initInstance(HINSTANCE hInstance)
{
WNDCLASS wc = {};
wc.lpfnWndProc = WinProc;
wc.hInstance = hInstance,
wc.lpszClassName = MAINWINDOW_CLASS_NAME;
return RegisterClass(&wc);
}
HWND initWindow(HINSTANCE hInstance)
{
HWND hwndMain = CreateWindow(
MAINWINDOW_CLASS_NAME, // The class name
"Text Editor", // The window name
WS_OVERLAPPEDWINDOW,// The window style
CW_USEDEFAULT, // The x pos
CW_USEDEFAULT, // The y pos
CW_USEDEFAULT, // The width
CW_USEDEFAULT, // The height
(HWND) NULL, // Handle to parent
(HMENU) NULL, // Handle to the menu
hInstance, // Handle to the instance
NULL // Window creation data
);
if (!hwndMain) {
return NULL;
}
else {
return hwndMain;
}
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
HWND htextArea;
char sztestText[] = "I should be able to see this text.";
switch (uMsg) {
case WM_CREATE:
htextArea = createTextArea(hwnd);
SendMessage(htextArea, WM_SETTEXT, 0, (LPARAM) sztestText);
break;
case WM_PAINT:
break;
case WM_CLOSE:
break;
case WM_SIZE:
RECT rectMainWindow;
GetWindowRect(hwnd, &rectMainWindow);
INT x = rectMainWindow.right - rectMainWindow.left + 50;
INT y = rectMainWindow.bottom - rectMainWindow.top + 50;
MoveWindow(htextArea, 0, 0, x, y, TRUE);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
/*******************************************************************/
HWND createTextArea(HWND hParent) {
return CreateWindow(
TEXTAREA_CLASS_NAME, // Class control name
NULL, // Title
WS_CHILD | WS_VISIBLE | ES_MULTILINE, // Styles
0, 0, 0, 0, // Sizing and position
hParent,
(HMENU) MAKEINTRESOURCE(100),
(HINSTANCE) GetWindowLong(hParent, GWL_HINSTANCE),
NULL
);
}
You've defined htextArea as a local variable in WinProc and so every time your window procedure is called its value will be uninitialized. You should make it static or move it to global data outside the function.
(The actual problem is that when you get a WM_SIZE message, you've lost the handle to the edit control, and so its size remains as 0,0).
Related
how i can move my window when middle mouse button pressed?
in case with left mouse button it would be
case WM_LBUTTONDOWN:
{
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
return 0;
but it does not work with middle button
case WM_MBUTTONDOWN:
{
SendMessage(hwnd, WM_NCMBUTTONDOWN, HTCAPTION, 0);
}
return 0;
but i am not sure about WM_NCMBUTTONDOWN
i`m out of variants, need help please
You have to do this the hard way I'm afraid. I tried all the obvious things and WM_NCHITTEST doesn't cut it if you want to drag the window with anything other than the left mouse button.
Here's some code that works for me (tested on Windows 10). I've excluded error checking for brevity:
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
// WndProc
LRESULT CALLBACK MyWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static int xClick, yClick;
switch (uMsg)
{
case WM_NCMBUTTONDOWN:
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
{
SetCapture (hWnd);
POINT pt = { GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam) };
if (uMsg == WM_NCMBUTTONDOWN)
ScreenToClient (hWnd, &pt);
xClick = pt.x;
yClick = pt.y;
return 0;
}
case WM_LBUTTONUP:
case WM_MBUTTONUP:
ReleaseCapture ();
return 0;
case WM_MOUSEMOVE:
{
if (GetCapture() == hWnd)
{
RECT wr;
GetWindowRect (hWnd, &wr);
int xMouse = GET_X_LPARAM (lParam);
int yMouse = GET_Y_LPARAM (lParam);
int xWindow = wr.left + xMouse - xClick;
int yWindow = wr.top + yMouse - yClick;
SetWindowPos (hWnd, NULL ,xWindow, yWindow, 0, 0 , SWP_NOSIZE | SWP_NOZORDER);
}
return 0;
}
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
// WinMain
int CALLBACK _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
HINSTANCE hInstance = NULL;
WNDCLASS wc = { };
wc.lpszClassName = __T ("MyWindowClass");
wc.lpfnWndProc = MyWndProc;
RegisterClass (&wc);
HWND hWnd = CreateWindow (wc.lpszClassName, __T ("My Window"),
WS_CAPTION | WS_BORDER | WS_VISIBLE, 100, 100, 200, 200, NULL, NULL, hInstance, 0);
MSG msg;
while (GetMessage (&msg, NULL, 0, 0))
DispatchMessage (&msg);
return 0;
}
Hope this helps.
The DATETIMEPICKERINFOstructure obtained by sending the DTM_GETDATETIMEPICKERINFOmessage has a field hwndEdit which might be what I'm looking for. However, I'm getting always NULL for it so I'm wondering what's its actual meaning. If not, is there a way to get the handle of the entry field?
hwndEdit only seems to be valid when the control has the DTS_APPCANPARSE style and you click the date text with the mouse (I tested this with OutputDebugString and a timer). The edit control is created and destroyed dynamically. The hwndUD handle is only valid if DTS_UPDOWN is set and the hwndDropDown is only valid while the dropdown is visible.
It is not called out in the documentation but DTM_GETDATETIMEPICKERINFO is marked Vista+ and this often means the feature is only implemented in ComCtl32 v6 so you also have to make sure you have a manifest that requests this version.
To change the color you can try DTM_SETMCCOLOR but only MCSC_BACKGROUND is documented to work when Visual Styles are active.
I'm afraid there is no way to get what you wanted. I just created a simple Win32 application just to test the possibility. If I use the DTM_GETDATETIMEPICKERINFO, hwndDropDown, hwndEdit and hwndUD give me NULL. If I try to enum child window, well before I do so I check it with Spy++, no luck, there is no child window associated with it.
Finally, I tried GetFocus() and WindowFromPoint(), both give me the HWND of the DateTimePicker itself only.
Here is my testing code:
#pragma comment(lib, "comctl32.lib")
#include <windows.h>
#include <tchar.h>
#include <commctrl.h>
enum MYID {
MYID_FIRST = WM_APP,
MYID_DTP
};
LPCTSTR const g_MyWndClass = _T("DTPTest");
LPCTSTR const g_MyWndTitle = _T("DTPTest");
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void OnWindowCreate(HWND);
void OnTimer(HWND);
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int nCmdShow)
{
INITCOMMONCONTROLSEX icex{};
icex.dwSize = sizeof(icex);
icex.dwICC = ICC_DATE_CLASSES;
InitCommonControlsEx(&icex);
WNDCLASSEX wcex{};
wcex.cbSize = sizeof(wcex);
wcex.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.lpfnWndProc = WndProc;
wcex.lpszClassName = g_MyWndClass;
wcex.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wcex);
HWND hwnd = CreateWindowEx(0,
g_MyWndClass, g_MyWndTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 600, 400,
nullptr, nullptr, nullptr, nullptr);
if (!hwnd) { return 99; }
SetTimer(hwnd, 0, 100, nullptr);
ShowWindow(hwnd, nCmdShow);
MSG msg{};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
switch (msg) {
case WM_CREATE:
OnWindowCreate(hwnd);
break;
case WM_TIMER:
OnTimer(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, w, l);
}
return 0;
}
void OnWindowCreate(HWND hwnd)
{
HWND hwndDTP = CreateWindowEx(0, DATETIMEPICK_CLASS, nullptr,
WS_CHILD | WS_VISIBLE | DTS_SHOWNONE,
20, 50, 220, 20,
hwnd, reinterpret_cast<HMENU>(MYID_DTP), nullptr, nullptr);
DATETIMEPICKERINFO info{};
info.cbSize = sizeof(DATETIMEPICKERINFO);
SendMessage(hwndDTP, DTM_GETDATETIMEPICKERINFO, 0,
reinterpret_cast<LPARAM>(&info));
if (!info.hwndDropDown && !info.hwndEdit && !info.hwndUD)
{
MessageBox(hwnd, _T("No luck with DTM_GETDATETIMEPICKERINFO"),
nullptr, MB_ICONERROR);
}
}
void OnTimer(HWND hwnd)
{
POINT pt{};
GetCursorPos(&pt);
HWND hwndPoint = WindowFromPoint(pt);
HWND hwndFocus = GetFocus();
TCHAR buf[99]{};
wsprintf(buf, _T("Pointing at %p, focusing %p"),
hwndPoint, hwndFocus);
SetWindowText(hwnd, buf);
}
I've started Direct2D from a very simple example.
Acquire the factory and ID2D1HwndRenderTarget, then handle WM_PAINT message to draw just a background with a solid color using "Clear" function.
It's work fine, until I start to move the window. When the window is moving it turns gray like nothing is drawing. I've tried to draw an ellipse, and the result is the same.
How could one present the window content with the window moving?
P.S. In case the code is needed
#include <Windows.h>
#include <d2d1_1.h>
#pragma comment(lib,"d2d1")
ID2D1Factory * d2factory_ptr = NULL;
ID2D1HwndRenderTarget * renderTarget_ptr = NULL;
LRESULT CALLBACK mainWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(
HINSTANCE hInstance
, HINSTANCE prevInstance
, LPWSTR cmd
, int nCmdShow
) {
WNDCLASSEX wndClassStruct;
ZeroMemory(&wndClassStruct, sizeof(WNDCLASSEX));
wndClassStruct.cbSize = sizeof(WNDCLASSEX);
wndClassStruct.hbrBackground = (HBRUSH)COLOR_WINDOW;
wndClassStruct.style = CS_HREDRAW | CS_VREDRAW;
wndClassStruct.hInstance = hInstance;
wndClassStruct.lpfnWndProc = mainWinProc;
wndClassStruct.lpszClassName = TEXT("MainWnd");
RegisterClassEx(&wndClassStruct);
RECT windowRect = { 0,0,640,480};
AdjustWindowRectEx(&windowRect, WS_OVERLAPPEDWINDOW, 0, WS_EX_APPWINDOW);
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, TEXT("MainWnd"), TEXT("Direct 2D Test Window"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, NULL, NULL, hInstance, 0);
{
D2D1_FACTORY_OPTIONS fo;
ZeroMemory(&fo, sizeof(D2D1_FACTORY_OPTIONS));
IID const factoryIID = IID_ID2D1Factory1;
HRESULT res = S_OK;
if (S_OK != (res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factoryIID, &fo, &d2factory_ptr))) {
return 0;
}
RECT clientRect;
GetClientRect(hWnd, &clientRect);
D2D1_RENDER_TARGET_PROPERTIES renderTargetProps;
ZeroMemory(&renderTargetProps, sizeof(D2D1_RENDER_TARGET_PROPERTIES));
renderTargetProps.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
renderTargetProps.pixelFormat = (D2D1_PIXEL_FORMAT) { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED };
renderTargetProps.dpiX = 0;
renderTargetProps.dpiY = 0;
renderTargetProps.usage = D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING;
renderTargetProps.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
D2D1_HWND_RENDER_TARGET_PROPERTIES hwndRenderProps;
ZeroMemory(&hwndRenderProps, sizeof(D2D1_HWND_RENDER_TARGET_PROPERTIES));
hwndRenderProps.hwnd = hWnd;
hwndRenderProps.pixelSize = (D2D1_SIZE_U) { clientRect.right - clientRect.left, clientRect.bottom - clientRect.top };
hwndRenderProps.presentOptions = D2D1_PRESENT_OPTIONS_NONE;
if (S_OK != (res = d2factory_ptr->lpVtbl->CreateHwndRenderTarget(d2factory_ptr, &renderTargetProps, &hwndRenderProps, &renderTarget_ptr))) {
return 0;
}
}
ShowWindow(hWnd, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DestroyWindow(hWnd);
if(NULL != renderTarget_ptr)
renderTarget_ptr->lpVtbl->Base.Base.Base.Release((IUnknown*)renderTarget_ptr);
if (NULL != d2factory_ptr)
d2factory_ptr->lpVtbl->Base.Release((IUnknown*)d2factory_ptr);
return 0;
}
LRESULT onPaintMainWindow() {
ID2D1RenderTargetVtbl renderTargetFuncs = renderTarget_ptr->lpVtbl->Base;
ID2D1RenderTarget * This = (ID2D1RenderTarget*)renderTarget_ptr;
D2D1_TAG tag1, tag2;
D2D1_COLOR_F backgroundClr = (D2D1_COLOR_F) { 0.0, 0.5, 1.0, 1.0 };
renderTargetFuncs.BeginDraw(This);
renderTargetFuncs.Clear(This, &backgroundClr);
renderTargetFuncs.EndDraw(This, &tag1, &tag2);
return 0;
}
LRESULT CALLBACK mainWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (WM_PAINT == uMsg)
return onPaintMainWindow();
if (WM_DESTROY == uMsg) {
PostQuitMessage(0); return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
Configure your WNDCLASSEX to not have a background brush.
Replace this line:
wndClassStruct.hbrBackground = (HBRUSH)COLOR_WINDOW;
With this:
wndClassStruct.hbrBackground = GetStockObject(NULL_BRUSH);
Alternatively, you can modify mainWndProc to swallow the WM_ERASEBKGND messages. It achieves the same effect by not allowing the window to erase itself before issuing a WM_PAINT.
LRESULT CALLBACK mainWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (WM_PAINT == uMsg)
return onPaintMainWindow();
if (uMsg == WM_ERASEBKGND)
{
// ignore requests to erase the background since the wm_paint
// handler is going to redraw the entire window.
return 0;
}
if (WM_DESTROY == uMsg) {
PostQuitMessage(0); return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
I am learning windows programming with the help of MSDN.Why would somebody initialize an object like the following?
WNDCLASS wc = { };
Will this zero all the memory of the object?
Whole source code is following:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Presumably to take advantage of Automatic Initialization.
Reference:
C++03 Standard 8.5.1 Aggregates
Para 7:
If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized (8.5).
[Example:
struct S { int a; char* b; int c; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that is,0. ]
While Value Initialization is defined in,
C++03 8.5 Initializers
Para 5:
To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible
default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static
data member and base-class component of T is value-initialized;
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized
MSDN doc's for MoveWindow() says:
"If the bRepaint parameter is TRUE, the system sends the WM_PAINT message to the window procedure immediately after moving the window (that is, the MoveWindow function calls the UpdateWindow function)."
But when I call GetUpdateRect() after MoveWindow(), while processing the WM_LBUTTONDOWN message in the parent, I get a beep, which shows that the child is invalid. What is the explanation ???
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
HINSTANCE ghInstance;
LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);
LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASSEX wndclassx;
ghInstance = hInstance;
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = 0;
wndclassx.lpfnWndProc = WindowProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclassx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclassx.lpszMenuName = NULL;
wndclassx.lpszClassName = _T("ParentWindow");
wndclassx.hIconSm = NULL;
if( !RegisterClassEx(&wndclassx) ) return 0;
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = 0;
wndclassx.lpfnWndProc = ChildProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = 0;
wndclassx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclassx.lpszMenuName = NULL;
wndclassx.lpszClassName = _T("ChildWindow");
wndclassx.hIconSm = NULL;
if( !RegisterClassEx(&wndclassx) ) return 0;
if( !(hWnd = CreateWindow(_T("ParentWindow"), _T("Parent Window"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance,
NULL)) ) return 0;
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
while( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
HWND hWnd;
switch ( message )
{
case WM_CREATE:
CreateWindow(_T("ChildWindow"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 100, 100, hwnd, (HMENU)0,
ghInstance, NULL);
break;
case WM_LBUTTONDOWN:
hWnd = GetWindow(hwnd, GW_CHILD);
MoveWindow(hWnd, 10, 10, 200, 200, true);
if( GetUpdateRect(hWnd, NULL, FALSE) ) MessageBeep(-1);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
The MSDN doc's is wrong. MoveWindow() with TRUE doesn't call UpdateWindow() as the documentation says. It just invalidates the window client area. If I call UpdateWindow() just after MoveWindow() the program runs as expected.
I tried it myself and WM_PAINT is triggered before the if(GetUpdateRect()) is. Also, GetUpdateRect returns FALSE for me.
I'm running Visual Studio 2008 on XP.
I guess it could depend on what compiler you are using, what operating system that is used and whatnot. According to the code you passed everything is done in the same thread, but if it is a multithreaded program I think that this could inflict some issues as well.