Strange phenomenon about MFC class CRect? - mfc

I have a dialog based program and two range CRect rc1(0,0,1024,768), rc2(0,1,1024,768). I use MoveWindow function to move the dialog, the dialog will appear at the center of the screen when using rc1, but the left for rc2?
Why?

This is a "feature" of MFC. A dialog with coordinates 0,0 will automatically be centered by the CDialog::CheckAutoCenter() function that is located in dlgcore.cpp which is one of the source files of MFC. This function is called by MFC after OnInitdialog.

Related

GetWindowRect coordinates not screen-relative

I am working in Visual Studio 2008 C++. I have an MFC dialog with a control inside it. I am trying to position another dialog in the control.
SetWindowPos() on the second dialog is clearly using screen coordinates, so I need to get the screen coordinates of the control or the parent dialog. The MSDN documentation says GetWindowRect() provides "screen coordinates relative to the upper-left corner of the display screen" but this is NOT what I am getting. On the control it gives coordinates relative to the parent. On the parent it gives left=0 and top=0. I have tried the rectangle from GetWindowPlacement() as well and it gives the same thing. Everything is relative to the parent.
Why is GetWindowRect() not returning screen-relative coordinates? Is there another way to get them?
I'm not new to programming, but fairly new to Windows programming, Visual Studio, and MFC, so I may be missing something obvious.
Here is what I am doing in OnInitDialog for the parent dialog:
// TestApp message handlers
BOOL TestApp::OnInitDialog()
{
CDialog::OnInitDialog();
FILE * pFile = fopen("out.txt","w");
CRect winRect;
GetWindowRect(&winRect);
fprintf(pFile,"left=%li top=%li right=%li bottom=%li\n",winRect.left,winRect.top,winRect.right,winRect.bottom); fflush(pFile);
fclose(pFile);
return TRUE; // return TRUE unless you set the focus to a control
}
When run, the dialog does NOT appear at the upper-left corner of the screen, but out.txt contains:
left=0 top=0 right=297 bottom=400
OnInitDialog is called by the framework, before the dialog is shown. At this point, neither the final size nor position are known:
Windows sends the WM_INITDIALOG message to the dialog box during the Create, CreateIndirect, or DoModal calls, which occur immediately before the dialog box is displayed.
The final size and position of a dialog are the result of window positioning negotiations. The first message sent to a dialog where this information is available is WM_WINDOWPOSCHANGED. Using MFC, this message is handled through CWnd::OnWindowPosChanged. Custom handling code can be implemented by overriding OnWindowPosChanged in your CDialog-derived class.
As written in the other answer:
OnInitDialog is called before the window is moved to its final position. If you call GetWindowRect later you'll see it return the proper coordinates.
Just use PostMessage with a WM_APP+n message. This message will arrive when the message pump is running and the message will arrive when the window is positioned and shown on the screen.
Or use a timer. This has the same effect.
OnInitDialog is called before the window is moved to its final position. If you call GetWindowRect later you'll see it return the proper coordinates.

Drawing static text on transparent window

I am trying to display static text directly inside a game's window. I am writing a standard win32 dll that the game loads. The DLL creates a borderless and transparent dialog window that always lies on top of the game's window and fills the game's client area. The only problem is that when I make the dialog window transparent, the static text I put on the dialog becomes invisble too. Is there a way that I can make the dialog window transparent but not the text on it?

Child Window painting problem on Vista only

I have a dialog-based MFC C++ app. My dialog displays a number of "pages" (similar to a tab page or property dialog box).
I display each "page" by displaying a Child window over the top of the parent's client area. This works fine on Vista until I then open another window on top of the child.
Vista then seems to draw a thick white rectangular frame within my parent dialog box which paints over the top of my "page" child window(s). If I move another window over the top of this white rectangle, it will repaint the obscured area just fine.
Can somebody please tell me what is going on? Is Vista trying to clear my non-client (frame) area using incorrect coordinates perhaps?
My parent dialog is a skinned class derived from CDialog which handles the painting of my own window titlebar and frames. I've found that if I don't call CDialog::OnNcActivate() within my own OnNcActivate() method, the white rectangle doesn't appear. Of course if I do this then I can't use my child windows.. but OnNcActivate would appear to be related to the problem.
I've figured out the problem.. I shouldn't be calling CDialog::OnNcActivate() - I should have just been returning TRUE instead. All working fine now.

Reposition dialog controls when resizing a dialog so that they are consistent between operating systems using mfc C++

Currently I'm repositioning dialog controls when the dialog is resized like this:
// Get the list control rect.
CRect listRect;
list->GetWindowRect(&listRect);
ScreenToClient(listRect);
// Get the dialog Rect.
CRect dialogRect;
GetWindowRect(&dialogRect);
ScreenToClient(dialogRect);
list->MoveWindow(listRect.left, listRect.top,
dialogRect.right - (2 * listRect.left), dialogRect.bottom - 100);
This works great in Windows XP, but when I tried in Windows Vista the positioning was off. I think this must be down to larger dialog borders and captions in Windows Vista dialogs, and the fact that GetWindowRect has the following entry in the documentation:
The dimensions are given in screen coordinates relative to the upper-left corner of the display screen. The dimensions of the caption, border, and scroll bars, if present, are included.
So my question is, how do I reposition dialog controls when resizing a dialog so that they are consistent between operating systems? Thanks
You should use GetClientRect instead of GetWindowRect followed by ScreenToClient -- the former returns the extents of the client part of the window (i.e. without borders), whereas the latter retrieves the extents of the whole window including non-client parts (albeit in client coordinates).
// Get the list control rect.
CRect listRect;
list->GetWindowRect(&listRect);
dlg->ScreenToClient(&listRect);
// Get the dialog Rect.
CRect dialogRect;
dlg->GetClientRect(&dialogRect);
list->MoveWindow(listRect.left, listRect.top, dialogRect.right - (2 * listRect.left), dialogRect.bottom - 100);

OwnerDrawn control in MFC

I am creating a MFC application in which there is a skin library which handles the UI effect of rendering the controls (it gets called in oninitdialog). But, meanwhile, I have also the requirement of displaying an icon on the buttons. For this, I am marking the buttons as ownerdrawn=true, and able to display icon, but in this case, skin effect is not taking place on those buttons whose ownerdrawing is done by me. So, my question is, how do I ensure that a control gets ownedrawn by me, and also by any other library.
Call the default handler for OnPaint to make sure the skinning library has a chance to draw the button, then draw your own content over the top.
void OnPaint()
{
Default();
CClientDC dc(this);
// your painting code goes here
}
You don't need owner-draw to display icons in buttons !