Sign in to follow this  

Right/bottom-aligning child windows within a parent in Windows

This topic is 2654 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The problem seems trivial with a trivial solution: respond to parent window's WM_SIZE message and set the position of all child windows that are to be aligned relative to the right/bottom of the parent window (using SetWindowPos()). Unfortunately, this only yields nice results when the user is resizing the parent using the right or bottom edge - when resizing using the left/top edges, the right/bottom aligned children make a very unnatural jolt before settling to their proper position. This jump seems to be equal to the amount dragged (eg he faster you resize the window, the more jitter you see - at worst several hundred pixels whichm, needless to say, looks very unnatural).

I've been scouring the web to find a solution to this and it seems I either can't come up with suitable search terms or this is not a well-documented case. Anyone here have some experience with this?

Share this post


Link to post
Share on other sites
Wow, I never noticed that (or rather never really paid attention to fast resizing), and I've been programming Windows for a long time (it's kind of rare to size a window from the upper left anyways). It even does that with status bars and even in this Firefox window that I am on. It's not a strong jolt though. But you're right. It might not do this if the control was windowless instead.

EDIT: One thing I just tested right now with status bars is that you can hide and show the window in WM_SIZE and it stops that.

[Edited by - yadango on September 2, 2010 2:11:15 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by yadango
Wow, I never noticed that (or rather never really paid attention to fast resizing), and I've been programming Windows for a long time (it's kind of rare to size a window from the upper left anyways). It even does that with status bars and even in this Firefox window that I am on. It's not a strong jolt though. But you're right. It might not do this if the control was windowless instead.

EDIT: One thing I just tested right now with status bars is that you can hide and show the window in WM_SIZE and it stops that.


Hm - how do you mean? You mean hide and immediately show the parent window? It just causes the window to become invisible for a brief moment for me, which is expected and even more epileptic than the regular jumping. Or did you have something different in mind?

I've been trying this out in various programs and just about all of them seem to have this jumpy effect (even VS2008). I'm not sure why this is not something that would be attended to by MS - it doesn't seem like a difficult or overly involved thing to fix... It's really ugly and a lot of applications make great use of attaching somekind of a toolbar or status bar to the right side of the main window (Photoshop and just about any 3D modeling software come to mind first).

Share this post


Link to post
Share on other sites
Something like this (it even works when I drag the size box). It is code from one of my win32 application templates. Though you might want to try iMalc's DeferWindowPos thingy first. I know flashing is one of things everyone likes to get rid of, but even Visual Studio's status bar exhibits this behavior as well, so don't feel bad about it :-). I still think windowless is the way to go if you don't want this behavior (notice this source box doesn't do it, since I think browser controls are windowless because there is a limit to the number of window handles you can have open).


BOOL LayoutMainWindow(void)
{
// validate presence of client window
HWND client = GetMainClient();
if(!client) return FALSE;

// hide status bar
ShowWindow(GetMainStatusBar(), SW_HIDE);

// resize tool bar
TB_AutoSize(GetMainToolBar());
SIZE toolsize;
GetClientDimensions(GetMainToolBar(), &toolsize);

// resize status bar
DivideMainStatusBar();
SendMessage(GetMainStatusBar(), WM_SIZE, 0, 0);
SIZE statsize;
GetClientDimensions(GetMainStatusBar(), &statsize);

// resize client
LONG x0 = 0;
LONG y0 = toolsize.cy;
LONG dx = client_dx;
LONG dy = client_dy - toolsize.cy - statsize.cy;
MoveWindow(client, x0, y0, dx, dy, TRUE);

// reshow status bar
ShowWindow(GetMainStatusBar(), SW_SHOW);

return TRUE;
}



Share this post


Link to post
Share on other sites
I'll try the DefferedWindowPos method tomorrow, although I have doubts about it. The method you showed doesn't seem to be working for me for a gadget-bar like case. I haven't tried this, but one thing I thought of giving a shot at was capturing the DC of the sidebar and blitting it directly to the parent. I'm faily sure this won't work either as observing the way Windows is drawing the child windows seems to indicate that it's not a positioning problem, but a syncing problem between resizing and painting, which cannot be overcome that easily. You get that from spewing out WM_SIZE and WM_PAINT messages arbitrarily (like Windows does) - and as far I can see the only way to overcome this would be to disable updates for something like 200 ms at a time for the parent, which would get rid of the jumping, but would introduce choppiness. Again, I'll try it out tomorrow.

Share this post


Link to post
Share on other sites
You may also want to try experimenting with using the SWP_DEFERERASE, SWP_NOREDRAW, or SWP_NOCOPYBITS flags of SetWindowPos or DeferWindowPos.
I'm sure that somewhere amoungst all of that, it can be done.

Share this post


Link to post
Share on other sites
Hmm - I'm not sure what's going on here, but it seems the following code fails to resize the windows:


HDWP wp;
if(wp = BeginDeferWindowPos(2))
{
wp = DeferWindowPos(wp, w0->GetHandle(), NULL, 0, 0, max(0, iWidth - 600), iHeight, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
wp = DeferWindowPos(wp, w1->GetHandle(), NULL, iWidth - 600, 0, 600, iHeight, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);
if(!EndDeferWindowPos(wp))
{ lout << "ewp fail" << endl; }
}
else
lout << "bwp fail" << endl;





None of the functions fail, but the windows aren't adjusted either. Am I missing something?

Share this post


Link to post
Share on other sites
I was having this exact problem until... I gave up.

Even MS Paint, which seems to not even resize the client/child area, has a status bar that flickers when you use the right or bottom resizer. That's a bit unimpressive for standard-as-it-gets MS software. I'm pretty sure my app's status bar doesn't flicker at all when resizing from the right/bottom.

I gave up trying but I'm eager to see if you find a solution. It would be nice to have an app that resizes more cleanly than even MS's software.

Share this post


Link to post
Share on other sites
Try this program Defend. Drag the upper left border edge of the window. At least on my computer (Windows 7 x64), the shifting of the status bar does not occur using my little hide/show trick. Still flickers a little when you drag the bottom right but oh well. Kind of sucks DeferWindowPos doesn't work with toolbars and status bars since these controls are typically responsible for sizing themselves (using TB_AUTOSIZE and forwarding a WM_SIZE to a status bar).

What I find really funny is that Visual Studio's status bar is actually a windowless control and it jumps around really bad ha ha ha even moreso than a regular status bar control.

Share this post


Link to post
Share on other sites
Quote:
Original post by yadango
Try this program Defend. Drag the upper left border edge of the window. At least on my computer (Windows 7 x64), the shifting of the status bar does not occur using my little hide/show trick. Still flickers a little when you drag the bottom right but oh well. Kind of sucks DeferWindowPos doesn't work with toolbars and status bars since these controls are typically responsible for sizing themselves (using TB_AUTOSIZE and forwarding a WM_SIZE to a status bar).

What I find really funny is that Visual Studio's status bar is actually a windowless control and it jumps around really bad ha ha ha even moreso than a regular status bar control.


I'm fairly sure there isn't a single working solution to this (I can't run the example you posted as it requires MSVCR100.dll and I'm too lazy to get it :) ). Visual Studio is one of the premium pieces of software out there and it has this issue; as does MS Word (2003 at least) - the help bar keeps jittering while resizing.

As I see it, the only painting/moving-based solution might be to emulate the drawback of the entire parent's client area, including the children, and also emulating DeferWindowPos to position the children manually (!). The ironic thing is that I'm actually doing most of that (the painting bit, that is), but I'm using HWND's (child windows) as canvases to draw on (a work area and a toolbar kind of thing that contains a number of other controls).

The issue seems to be that the windows "are repositioned twice", regardless of whether you're using DeferWindowPos() or not: once prior to resizing and once after and. Well, almost - I think this is due to the fact that the paint and resize messages aren't synced (a new WM_SIZE is spammed down the pipeline and the window borders and contents moved (scrolled, not redrawn) before painting the previous content finishes). I'll try disallowing a new resize increment while the parent is being invalidated and get back to you when I have something to report (not sure if I know how to do this with child HWND's yet, but I'll try to think of something) - it'll probably cause the resizing to be laggy, but it shouldn't flicker. Or then again...

Share this post


Link to post
Share on other sites
No dice. However, I did find this on stackoverflow, which seems to claim it does what we're trying to do with great success. I tried out a quick port of the posted code and I'm still getting the same results as before. I'm short on time and in a hurry ATM, though, so I might've missed something.

Share this post


Link to post
Share on other sites
I just tried their technique too... it solves the flicker problem with regular child windows, but the child windows still jump when the window is sized quickly. Looks like you can solve one problem but not both at the same time (jumping or flickering). Ha ha ha this sounds like a problem for Paul DiLascia... too bad he's not around anymore.


#include<windows.h>

static HINSTANCE basead = 0;
static LRESULT CALLBACK MainWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK RectWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);

int WINAPI WinMain(HINSTANCE basead, HINSTANCE, LPSTR, int)
{
// set base address
::basead = basead;

// register window
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = MainWndProc;
wcex.hInstance = basead;
wcex.hIcon = LoadIcon(0, IDI_APPLICATION);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName = 0;
wcex.lpszClassName = TEXT("MAINWINDOW");
wcex.hIconSm = LoadIcon(0, IDI_APPLICATION);
if(!RegisterClassEx(&wcex)) return -1;

// create window
DWORD style_ex = 0;
DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE;
int x = CW_USEDEFAULT, y = CW_USEDEFAULT;
int w = CW_USEDEFAULT, h = CW_USEDEFAULT;
HWND window = CreateWindowEx(style_ex, TEXT("MAINWINDOW"), TEXT("Simple Window"), style, x, y, w, h, 0, 0, basead, 0);
if(!window) return -1;
ShowWindow(window, SW_SHOW);
UpdateWindow(window);

// message loop
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
static HWND child1, child2;
static HWND child3, child4;
static bool sizemove = false;

switch(message) {
case(WM_CREATE) :
{
// do default
LRESULT retval = DefWindowProc(window, message, wparam, lparam);
if(retval == -1) return -1;

// register window
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
if(GetClassInfoEx(::basead, TEXT("RECTWINDOW"), &wcex) == FALSE) {
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = RectWndProc;
wcex.hInstance = ::basead;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = 0;
wcex.lpszClassName = TEXT("RECTWINDOW");
wcex.hIconSm = 0;
if(!RegisterClassEx(&wcex)) {
MessageBox(window, TEXT("Failed to register child window class."), TEXT("Error"), MB_ICONSTOP);
return -1;
}
}

// create windows
DWORD style_ex = 0;
DWORD style = WS_CHILD | WS_BORDER | WS_VISIBLE;
int x = 0, y = 0;
int w = 0, h = 0;
child1 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
child2 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
child3 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
child4 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
if(!child1) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
if(!child2) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
if(!child3) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
if(!child4) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
ShowWindow(child1, SW_SHOW); UpdateWindow(child1);
ShowWindow(child2, SW_SHOW); UpdateWindow(child2);
ShowWindow(child3, SW_SHOW); UpdateWindow(child3);
ShowWindow(child4, SW_SHOW); UpdateWindow(child4);

// do default
return retval;
}
case(WM_NCDESTROY) :
{
PostQuitMessage(0);
return DefWindowProc(window, message, wparam, lparam);
}
case(WM_NCCALCSIZE) :
{
BOOL calcsize = (BOOL)wparam;
LPNCCALCSIZE_PARAMS info = (LPNCCALCSIZE_PARAMS)lparam;
if(calcsize && sizemove) {
DefWindowProc(window, WM_NCCALCSIZE, FALSE, (LPARAM)&info->rgrc[0]);
info->rgrc[1] = info->rgrc[2];
return WVR_ALIGNLEFT | WVR_ALIGNTOP;
}
return DefWindowProc(window, message, wparam, lparam);
}
case(WM_ENTERSIZEMOVE) :
{
sizemove = true;
return DefWindowProc(window, message, wparam, lparam);
}
case(WM_EXITSIZEMOVE) :
{
sizemove = false;
return DefWindowProc(window, message, wparam, lparam);
}
case(WM_SIZE) :
{
if(!child1 || !child2) return DefWindowProc(window, message, wparam, lparam);;
if(!child3 || !child4) return DefWindowProc(window, message, wparam, lparam);;

int dx = LOWORD(lparam);
int dy = HIWORD(lparam);

int x0 = dx - 160;
int y0 = dy - 120;

//MoveWindow(child1, 0, 0, 160, 120, TRUE); // upper-left
//MoveWindow(child2, x0, 0, 160, 120, TRUE); // upper-right
//MoveWindow(child3, 0, y0, 160, 120, TRUE); // lower-left
//MoveWindow(child4, x0, y0, 160, 120, TRUE); // lower-right

HDWP hdwp = BeginDeferWindowPos(4);
if(hdwp) hdwp = DeferWindowPos(hdwp, child1, NULL, 0, 0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // upper-left
if(hdwp) hdwp = DeferWindowPos(hdwp, child2, NULL, x0, 0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // upper-right
if(hdwp) hdwp = DeferWindowPos(hdwp, child3, NULL, 0, y0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // lower-left
if(hdwp) hdwp = DeferWindowPos(hdwp, child4, NULL, x0, y0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // lower-right
if(hdwp) EndDeferWindowPos(hdwp);

return 0;
}
default : return DefWindowProc(window, message, wparam, lparam);
}
return 0;
}

LRESULT CALLBACK RectWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message) {
case(WM_NCDESTROY) : {
return DefWindowProc(window, message, wparam, lparam);
}
default : return DefWindowProc(window, message, wparam, lparam);
}
return 0;
}







[Edited by - yadango on September 4, 2010 4:11:27 PM]

Share this post


Link to post
Share on other sites
Hmmm just a quick question, what's the difference between jumping and flickering for you?

I haven't had a chance to try this still, but I ask because I distinguish a difference as well in my own app, but what I refer to as flickering was a problem solved easily.

I was called the Render() function of DirectX everytime the messages WM_SIZE or WM_SIZING were sent. If I did it this way, I got flickering. If I only used WM_SIZE, I got something ugly (nothing rendered while actually sizing). If I only used WM_SIZING, there was no flickering at all.

That's just my definition of flickering and jumping. Doing it this way did remove flickering, which was indeed quite ugly, and only left the possibility of the child window size being a little behind the parent window's border, which is what I assume you mean by jumping. While resizing, it was actually possible to stop moving the mouse while still holding the button down, and catch the child window waiting at the wrong size.

Anyway, the point is, if you're still getting jumping after this new code you tried.... isn't that where we were already stuck?

Share this post


Link to post
Share on other sites
IMO the redraws in GDI (regular WinAPI) are cleaner with this code, although the jumping's still there.

yadango - it seems to me your post implies that you can get rid of the jumping. How? For child windows, that is, in my case - I've no experience or particular interest in delving into toolbars at this time.

Share this post


Link to post
Share on other sites
Hey Defend, yeah, you have flashing and jumping right. I think irreversible and I are trying to fix this problem below... I got it to avoid jumping using status bars using the hiding trick, but it doesn't work in the below case.



This program jumps.

#include<windows.h>

static HINSTANCE basead = 0;
static LRESULT CALLBACK MainWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK RectWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);

int WINAPI WinMain(HINSTANCE basead, HINSTANCE, LPSTR, int)
{
// set base address
::basead = basead;

// register window
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = MainWndProc;
wcex.hInstance = basead;
wcex.hIcon = LoadIcon(0, IDI_APPLICATION);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName = 0;
wcex.lpszClassName = TEXT("MAINWINDOW");
wcex.hIconSm = LoadIcon(0, IDI_APPLICATION);
if(!RegisterClassEx(&wcex)) return -1;

// create window
DWORD style_ex = 0;
DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE;
int x = CW_USEDEFAULT, y = CW_USEDEFAULT;
int w = CW_USEDEFAULT, h = CW_USEDEFAULT;
HWND window = CreateWindowEx(style_ex, TEXT("MAINWINDOW"), TEXT("Simple Window"), style, x, y, w, h, 0, 0, basead, 0);
if(!window) return -1;
ShowWindow(window, SW_SHOW);
UpdateWindow(window);

// message loop
MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
static HWND child1, child2;
static HWND child3, child4;
static int client_dx;
static int client_dy;

switch(message) {
case(WM_CREATE) :
{
// do default
LRESULT retval = DefWindowProc(window, message, wparam, lparam);
if(retval == -1) return -1;

// register window
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
wcex.cbSize = sizeof(wcex);
if(GetClassInfoEx(::basead, TEXT("RECTWINDOW"), &wcex) == FALSE) {
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = RectWndProc;
wcex.hInstance = ::basead;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wcex.lpszMenuName = 0;
wcex.lpszClassName = TEXT("RECTWINDOW");
wcex.hIconSm = 0;
if(!RegisterClassEx(&wcex)) {
MessageBox(window, TEXT("Failed to register child window class."), TEXT("Error"), MB_ICONSTOP);
return -1;
}
}

// create windows
DWORD style_ex = 0;
DWORD style = WS_CHILD | WS_CLIPSIBLINGS | WS_BORDER | WS_VISIBLE;
int x = 0, y = 0;
int w = 0, h = 0;
child1 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
child2 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
child3 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
child4 = CreateWindowEx(style_ex, TEXT("RECTWINDOW"), 0, style, x, y, w, h, window, 0, basead, 0);
if(!child1) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
if(!child2) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
if(!child3) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
if(!child4) { MessageBox(window, TEXT("Failed to create child window."), TEXT("Error"), MB_ICONSTOP); return -1; }
ShowWindow(child1, SW_SHOW); UpdateWindow(child1);
ShowWindow(child2, SW_SHOW); UpdateWindow(child2);
ShowWindow(child3, SW_SHOW); UpdateWindow(child3);
ShowWindow(child4, SW_SHOW); UpdateWindow(child4);

// do default
return retval;
}
case(WM_NCDESTROY) :
{
PostQuitMessage(0);
return DefWindowProc(window, message, wparam, lparam);
}
case(WM_SIZE) :
{
if(!child1 || !child2) return DefWindowProc(window, message, wparam, lparam);
if(!child3 || !child4) return DefWindowProc(window, message, wparam, lparam);

client_dx = LOWORD(lparam);
client_dy = HIWORD(lparam);

int x0 = client_dx - 160;
int y0 = client_dy - 120;

HDWP hdwp = BeginDeferWindowPos(4);
if(hdwp) hdwp = DeferWindowPos(hdwp, child1, NULL, 0, 0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // upper-left
if(hdwp) hdwp = DeferWindowPos(hdwp, child2, NULL, x0, 0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // upper-right
if(hdwp) hdwp = DeferWindowPos(hdwp, child3, NULL, 0, y0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // lower-left
if(hdwp) hdwp = DeferWindowPos(hdwp, child4, NULL, x0, y0, 160, 120, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); // lower-right
if(hdwp) EndDeferWindowPos(hdwp);

InvalidateRect(window, NULL, TRUE);
return 0;
}
case(WM_PAINT) :
{
PAINTSTRUCT ps;
HDC winDC = BeginPaint(window, &ps);

// window rect
RECT rect;
GetClientRect(window, &rect);
int dx = rect.right - rect.left;
int dy = rect.bottom - rect.top;

// compute text rectangle
RECT textrect = { 0, 0, 0, 0};
DrawText(winDC, TEXT("Drag the upper-left border. Notice the bottom-right box tweeks!"), -1, &textrect, DT_SINGLELINE | DT_CALCRECT);
int text_dx = textrect.right - textrect.left;
int text_dy = textrect.bottom - textrect.top;

// compute centered text rectangle
rect.left = dx/2 - text_dx/2;
rect.right = dx/2 + text_dx/2;
rect.top = dy/2 - text_dy/2;
rect.bottom = dy/2 + text_dy/2;

// draw text
DrawText(winDC, TEXT("Drag the upper-left border. Notice the bottom-right box tweeks!"), -1, &rect, DT_SINGLELINE);

EndPaint(window, &ps);
return 0;
}
default : return DefWindowProc(window, message, wparam, lparam);
}
return 0;
}

LRESULT CALLBACK RectWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message) {
case(WM_PAINT) : {
PAINTSTRUCT ps;
HDC winDC = BeginPaint(window, &ps);
RECT rect = { 0, 0, 0, 0};
GetClientRect(window, &rect);
SelectObject(winDC, GetStockObject(LTGRAY_BRUSH));
PatBlt(winDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, PATCOPY);
EndPaint(window, &ps);
break;
}
default : return DefWindowProc(window, message, wparam, lparam);
}
return 0;
}


Share this post


Link to post
Share on other sites

This topic is 2654 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this