Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Window Width and Height

gdbgdb Member Posts: 4
Good morning,

The code below shows the width and height of
the window whenever it's resized.

However, when it's minimized and then restored
to its original position the program fails.

I know the message is captured by
"case WM_SIZE:" even in this scenario,
because if I insert "MessageBox(hwnd, s,
"Window", MB_OK);" in the code,
the coordinates are shown.

How to fix this code to make it show the
window width and height in every case?

Best,

Geraldo

#include

HWND hwndMain;

LRESULT CALLBACK MainWndProc(HWND hwnd,
UINT msg,WPARAM wParam,LPARAM lParam);

int WINAPI
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPSTR lpCmdLine,
INT nCmdShow)
{
MSG msg;
WNDCLASSEX wcx;

ZeroMemory(&wcx,sizeof(WNDCLASSEX));
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_HREDRAW|CS_VREDRAW |
CS_DBLCLKS ;
wcx.lpfnWndProc = (WNDPROC)MainWndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = NULL;
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcx.lpszMenuName = NULL;
wcx.lpszClassName = "Window";
wcx.hIconSm = NULL;

if (!RegisterClassEx(&wcx))
return 0;

hwndMain = CreateWindowEx(0,
"Window",
"Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
HWND_DESKTOP,
NULL,
hInstance,
NULL);

if (!hwndMain)
return 0;

ShowWindow(hwndMain,SW_SHOW);

while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

POINT pt;
LPTSTR s = new TCHAR[128];
PAINTSTRUCT ps;
HDC hdc;

LRESULT CALLBACK MainWndProc(HWND hwnd,
UINT msg,WPARAM wParam,LPARAM lParam)
{

switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;

case WM_SIZE:
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
wsprintf(s, "Window %d %d", pt.x, pt.y);
hdc = BeginPaint(hwnd, &ps );
TextOut(hdc, 0, 0, s, strlen(s));
EndPaint( hwnd, &ps );

//MessageBox(hwnd, s, "Window", MB_OK);
break;

default:
return DefWindowProc(hwnd,msg,wParam,
lParam);
}
return 0;
}

Comments

  • AsmGuru62AsmGuru62 Member Posts: 6,519
    : Good morning,
    :
    : The code below shows the width and height of
    : the window whenever it's resized.
    :
    : However, when it's minimized and then restored
    : to its original position the program fails.
    :
    : I know the message is captured by
    : "case WM_SIZE:" even in this scenario,
    : because if I insert "MessageBox(hwnd, s,
    : "Window", MB_OK);" in the code,
    : the coordinates are shown.
    :
    : How to fix this code to make it show the
    : window width and height in every case?
    :
    : Best,
    :
    : Geraldo
    :
    : [code]
    : #include
    :
    : HWND hwndMain;
    :
    : LRESULT CALLBACK MainWndProc(HWND hwnd,
    : UINT msg,WPARAM wParam,LPARAM lParam);
    :
    : int WINAPI
    : WinMain(HINSTANCE hInstance,
    : HINSTANCE hPrevInstance, LPSTR lpCmdLine,
    : INT nCmdShow)
    : {
    : MSG msg;
    : WNDCLASSEX wcx;
    :
    : ZeroMemory(&wcx,sizeof(WNDCLASSEX));
    : wcx.cbSize = sizeof(WNDCLASSEX);
    : wcx.style = CS_HREDRAW|CS_VREDRAW |
    : CS_DBLCLKS ;
    : wcx.lpfnWndProc = (WNDPROC)MainWndProc;
    : wcx.cbClsExtra = 0;
    : wcx.cbWndExtra = 0;
    : wcx.hInstance = hInstance;
    : wcx.hIcon = NULL;
    : wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    : wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    : wcx.lpszMenuName = NULL;
    : wcx.lpszClassName = "Window";
    : wcx.hIconSm = NULL;
    :
    : if (!RegisterClassEx(&wcx))
    : return 0;
    :
    : hwndMain = CreateWindowEx(0,
    : "Window",
    : "Window",
    : WS_OVERLAPPEDWINDOW,
    : CW_USEDEFAULT,CW_USEDEFAULT,
    : CW_USEDEFAULT,CW_USEDEFAULT,
    : HWND_DESKTOP,
    : NULL,
    : hInstance,
    : NULL);
    :
    : if (!hwndMain)
    : return 0;
    :
    : ShowWindow(hwndMain,SW_SHOW);
    :
    : while (GetMessage(&msg,NULL,0,0))
    : {
    : TranslateMessage(&msg);
    : DispatchMessage(&msg);
    : }
    : return msg.wParam;
    : }
    :
    : POINT pt;
    : LPTSTR s = new TCHAR[128];
    : PAINTSTRUCT ps;
    : HDC hdc;
    : [color=Red]RECT rect_ClientArea;[/color]
    :
    : LRESULT CALLBACK MainWndProc(HWND hwnd,
    : UINT msg,WPARAM wParam,LPARAM lParam)
    : {
    :
    : switch (msg)
    : {
    : case WM_DESTROY:
    : PostQuitMessage(0);
    : break;
    :
    : case [color=Red]WM_PAINT[/color]:
    : [color=Red]//pt.x = LOWORD(lParam);
    : //pt.y = HIWORD(lParam);[/color]

    : [color=Red]GetClientRect (hwnd, &rect_ClientArea);[/color]

    : wsprintf(s, "Window %d %d", [color=Red]rect_ClientArea.right, rect_ClientArea.bottom[/color]);
    : hdc = BeginPaint(hwnd, &ps );
    : TextOut(hdc, 0, 0, s, strlen(s));
    : EndPaint( hwnd, &ps );
    :
    : //MessageBox(hwnd, s, "Window", MB_OK);
    : break;
    :
    : default:
    : return DefWindowProc(hwnd,msg,wParam,
    : lParam);
    : }
    : return 0;
    : }
    : [/code]
    :
    [color=Blue]BeginPaint/EndPaint can only be used inside "case WM_PAINT" and nowhere else.

    Also, I changed the code, so now "MessageBox" is in case WM_PAINT. Do not call it there - it will cause the endless loop, because removal of message box will send another WM_PAINT. Just remove it.[/color]
  • gdbgdb Member Posts: 4
    Good evening,

    Guru, thank you so much: your code worked
    superbly!

    To implement the program a bit more, I tried to
    capture and show the coordinates of the mouse
    while I hover it over the window continuously,
    without interfering with already had been done
    so well with WM_PAINT.

    I used WM_MOUSEMOVE, but it didn't work.

    Do you have any idea to work this out?

    Best,

    Geraldo

    : : Good morning,
    : :
    : : The code below shows the width and height of
    : : the window whenever it's resized.
    : :
    : : However, when it's minimized and then restored
    : : to its original position the program fails.
    : :
    : : I know the message is captured by
    : : "case WM_SIZE:" even in this scenario,
    : : because if I insert "MessageBox(hwnd, s,
    : : "Window", MB_OK);" in the code,
    : : the coordinates are shown.
    : :
    : : How to fix this code to make it show the
    : : window width and height in every case?
    : :
    : : Best,
    : :
    : : Geraldo
    : :
    : : [code]:
    : : #include
    : :
    : : HWND hwndMain;
    : :
    : : LRESULT CALLBACK MainWndProc(HWND hwnd,
    : : UINT msg,WPARAM wParam,LPARAM lParam);
    : :
    : : int WINAPI
    : : WinMain(HINSTANCE hInstance,
    : : HINSTANCE hPrevInstance, LPSTR lpCmdLine,
    : : INT nCmdShow)
    : : {
    : : MSG msg;
    : : WNDCLASSEX wcx;
    : :
    : : ZeroMemory(&wcx,sizeof(WNDCLASSEX));
    : : wcx.cbSize = sizeof(WNDCLASSEX);
    : : wcx.style = CS_HREDRAW|CS_VREDRAW |
    : : CS_DBLCLKS ;
    : : wcx.lpfnWndProc = (WNDPROC)MainWndProc;
    : : wcx.cbClsExtra = 0;
    : : wcx.cbWndExtra = 0;
    : : wcx.hInstance = hInstance;
    : : wcx.hIcon = NULL;
    : : wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    : : wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    : : wcx.lpszMenuName = NULL;
    : : wcx.lpszClassName = "Window";
    : : wcx.hIconSm = NULL;
    : :
    : : if (!RegisterClassEx(&wcx))
    : : return 0;
    : :
    : : hwndMain = CreateWindowEx(0,
    : : "Window",
    : : "Window",
    : : WS_OVERLAPPEDWINDOW,
    : : CW_USEDEFAULT,CW_USEDEFAULT,
    : : CW_USEDEFAULT,CW_USEDEFAULT,
    : : HWND_DESKTOP,
    : : NULL,
    : : hInstance,
    : : NULL);
    : :
    : : if (!hwndMain)
    : : return 0;
    : :
    : : ShowWindow(hwndMain,SW_SHOW);
    : :
    : : while (GetMessage(&msg,NULL,0,0))
    : : {
    : : TranslateMessage(&msg);
    : : DispatchMessage(&msg);
    : : }
    : : return msg.wParam;
    : : }
    : :
    : : POINT pt;
    : : LPTSTR s = new TCHAR[128];
    : : PAINTSTRUCT ps;
    : : HDC hdc;
    : : [color=Red]RECT rect_ClientArea;[/color]
    : :
    : : LRESULT CALLBACK MainWndProc(HWND hwnd,
    : : UINT msg,WPARAM wParam,LPARAM lParam)
    : : {
    : :
    : : switch (msg)
    : : {
    : : case WM_DESTROY:
    : : PostQuitMessage(0);
    : : break;
    : :
    : : case [color=Red]WM_PAINT[/color]:
    : : [color=Red]//pt.x = LOWORD(lParam);
    : : //pt.y = HIWORD(lParam);[/color]
    :
    : : [color=Red]GetClientRect (hwnd, &rect_ClientArea);[/color]
    :
    : : wsprintf(s, "Window %d %d", [color=Red]rect_ClientArea.right, rect_ClientArea.bottom[/color]);
    : : hdc = BeginPaint(hwnd, &ps );
    : : TextOut(hdc, 0, 0, s, strlen(s));
    : : EndPaint( hwnd, &ps );
    : :
    : : //MessageBox(hwnd, s, "Window", MB_OK);
    : : break;
    : :
    : : default:
    : : return DefWindowProc(hwnd,msg,wParam,
    : : lParam);
    : : }
    : : return 0;
    : : }
    : : [/code]:
    : :
    : [color=Blue]BeginPaint/EndPaint can only be used inside "case
    : WM_PAINT" and nowhere else.
    :
    : Also, I changed the code, so now "MessageBox" is in case WM_PAINT.
    : Do not call it there - it will cause the endless loop, because
    : removal of message box will send another WM_PAINT. Just remove
    : it.[/color]


  • AsmGuru62AsmGuru62 Member Posts: 6,519
    [color=Blue]
    The main idea in Windows is to keep somewhere the data which needs to be drawn on a window surface. This data should be accessible from window procedure. In this case I made it global, however, the data can be attached to HWND for better localization (see SetWindowLong API). Next, if data changes in some way - your code should let HWND know that it needs to be redrawn (InvalidateRect/UpdateWindow pair of calls). There are two places to draw your window:

    1. WM_PAINT message
    2. From somewhere in code (not inside WM_PAINT) call GetDC()/ReleaseDC() and draw on THAT DC.

    The #2 should be used when there is no other choice and that is only when something is getting dragged (user HOLDS mouse button down!). Even in these (dragging) cases it is possible to use #1, but it is harder.

    Here is some working code - I tried it in VS 2005 (have fun!):
    [/color]
    [code]
    #include
    #include
    #include "MouseTest.h"

    #define MAX_LOADSTRING 100

    // Global Variables:
    HINSTANCE hInst; // current instance
    TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
    TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

    RECT rectClient;
    RECT rectPanel = { 8, 8, 240, 50 };
    POINT posMouse;

    // Forward declarations of functions included in this code module:
    ATOM MyRegisterClass(HINSTANCE hInstance);
    BOOL InitInstance(HINSTANCE, int);
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

    // -------------------------------------------------------------------------
    int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;

    // Initialize global strings
    lstrcpy (szTitle, _T ("Win32 Cursor Locator"));
    lstrcpy (szWindowClass, _T ("win32-cursor-locator"));
    MyRegisterClass (hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
    return FALSE;
    }

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    return (int) msg.wParam;
    }

    // -------------------------------------------------------------------------
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
    WNDCLASS wcex;

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(NULL, IDI_EXCLAMATION);
    wcex.hCursor = LoadCursor(NULL, IDC_CROSS);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = szWindowClass;

    return RegisterClass(&wcex);
    }

    // -------------------------------------------------------------------------
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
    HWND hWnd;

    hInst = hInstance; // Store instance handle in our global variable

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

    if (!hWnd)
    {
    return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    return TRUE;
    }

    // -------------------------------------------------------------------------
    void RefreshInfo (HWND hWnd)
    {
    InvalidateRect (hWnd, &rectPanel, FALSE);
    UpdateWindow (hWnd);
    }

    // -------------------------------------------------------------------------
    void DrawInfo (HDC hDC)
    {
    HBRUSH border = CreateSolidBrush (RGB (0, 64, 128));
    HBRUSH fill = CreateSolidBrush (RGB (255, 255, 204));

    FillRect (hDC, &rectPanel, fill);
    FrameRect (hDC, &rectPanel, border);

    DeleteObject (fill);
    DeleteObject (border);

    int iDefaultBkMode = SetBkMode (hDC, TRANSPARENT);
    HGDIOBJ hDefaultFont = SelectObject (hDC, (HFONT) GetStockObject (ANSI_FIXED_FONT));

    SetTextColor (hDC, RGB (55, 124, 208));

    TCHAR buf [64];
    wsprintf (buf, _T ("WIDTH:%5d; HEIGHT:%5d"), rectClient.right, rectClient.bottom);
    TextOut (hDC, rectPanel.left + 8, rectPanel.top + 8, buf, lstrlen (buf));

    wsprintf (buf, _T ("MOUSE -- X:%5d; Y:%5d"), posMouse.x, posMouse.y);
    TextOut (hDC, rectPanel.left + 8, rectPanel.top + 24, buf, lstrlen (buf));

    SelectObject (hDC, hDefaultFont);
    SetBkMode (hDC, iDefaultBkMode);
    }

    // -------------------------------------------------------------------------
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_MOUSEMOVE:
    posMouse.x = (int) LOWORD (lParam);
    posMouse.y = (int) HIWORD (lParam);
    RefreshInfo (hWnd);
    break;

    case WM_CREATE:
    GetClientRect (hWnd, &rectClient);
    break;

    case WM_SIZE:
    GetClientRect (hWnd, &rectClient);
    RefreshInfo (hWnd);
    break;

    case WM_COMMAND:
    wmId = LOWORD(wParam);
    wmEvent = HIWORD(wParam);
    // Parse the menu selections:
    switch (wmId)
    {
    case IDM_EXIT:
    DestroyWindow(hWnd);
    break;
    default:
    return DefWindowProc(hWnd, message, wParam, lParam);
    }
    break;

    case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    DrawInfo (hdc);
    EndPaint(hWnd, &ps);
    break;

    case WM_DESTROY:
    PostQuitMessage(0);
    break;

    default:
    return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
    }
    [/code]
Sign In or Register to comment.