 |
|
|
 |
|
 |
hi
i have a similar problem, only one level down ... i'm trying to center an image inside a CMDIChildWnd... well, actually, im trying to size the CMDIChildWnd so that the image fits the client area exactly. i know the image's dimensions, but using GetParentFrame()->MoveWindow(0,0,image->GetWidth(),image->GetHeight(),TRUE);
inside the cview class resizes the frame to these dimensions, and the frame includes the title bar at the top and the borders etc ... i just want to be able to specify the size of the client/drawing area in the window without having to worry about how many pixels the title bar covers!
thanks
jennifer
|
|
|
|
 |
|
 |
Here's a version which works with multiple monitors on systems which support them. (It will centre in the monitor with the mouse, by default, and should correctly handle negative screen coordinates.)
I hope it's useful...
// Give hWndRelative NULL to centre on the monitor with the mouse pointer.
// On systems before Windows 2000 and Windows 98 which don't support multiple monitors,
// the window centres on the desktop instead.
void LeoDavidsonUtils::CentreWindow(HWND hWndToMove, HWND hWndRelative)
{
RECT rectRelative;
if (NULL == hWndRelative)
{
OSVERSIONINFO osVerInfo;
ZeroMemory(&osVerInfo, sizeof(osVerInfo));
osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
POINT pointCursor;
MONITORINFO monitorInfo;
ZeroMemory(&monitorInfo, sizeof(monitorInfo));
monitorInfo.cbSize = sizeof(monitorInfo);
HMONITOR hMonitor;
if (GetVersionEx(&osVerInfo)
&& (((VER_PLATFORM_WIN32_NT == osVerInfo.dwPlatformId) && (5 <= osVerInfo.dwMajorVersion))
|| ((VER_PLATFORM_WIN32_WINDOWS == osVerInfo.dwPlatformId) && (0 < osVerInfo.dwMinorVersion)))
&& GetCursorPos(&pointCursor)
&& (NULL != (hMonitor = MonitorFromPoint(pointCursor, MONITOR_DEFAULTTOPRIMARY)))
&& GetMonitorInfo(hMonitor, &monitorInfo))
{
rectRelative = monitorInfo.rcWork;
}
else
{
GetWindowRect(GetDesktopWindow(), &rectRelative);
}
}
RECT rectToMove;
if (GetWindowRect(hWndToMove, &rectToMove))
{
// Handle negative screen co-ordinates (important with multiple monitors).
int relativeWidth = (rectRelative.right - rectRelative.left);
if (0 > relativeWidth)
{
relativeWidth = -relativeWidth;
}
int relativeHeight = (rectRelative.bottom - rectRelative.top);
if (0 > relativeHeight)
{
relativeHeight = -relativeHeight;
}
int toMoveWidth = (rectToMove.right - rectToMove.left);
if (0 > toMoveWidth)
{
toMoveWidth = -toMoveWidth;
}
int toMoveHeight = (rectToMove.bottom - rectToMove.top);
if (0 > toMoveHeight)
{
toMoveHeight = -toMoveHeight;
}
int x = rectRelative.left + ( (relativeWidth - toMoveWidth ) / 2 );
int y = rectRelative.top + ( (relativeHeight - toMoveHeight) / 2 );
SetWindowPos(hWndToMove, NULL, x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
}
}
|
|
|
|
 |
|
 |
Uh, of course, for it to actually run on systems which don't support multiple monitors you'll have to GetProcAddress the multi-monitor functions from User32.dll to avoid the implicit lookup causing the program not to load at all.
|
|
|
|
 |
|
 |
First, your code to detect the Windows version is bad. You're only checking the minor version for the Windows platform, which is fine for catching Win98/ME vs. Win95, but it has a couple of problems. Old versions of Win32s show up as Windows, not as a separate platform (this may not be documented, but it's bitten me before), so their minor version (.1) will pass your test. And if Microsoft releases a Windows product whose version number is 5.0 (I know, they promised that ME will be the last non-NT version of Windows ever--but then they promised the same thing with 98), its minor version (.0) will fail your test.
You could easily test for major.minor >= 4.1 properly (use the bIsWindows98OrLater example straight off the GetVersionEx help page), but there's a much better solution.
If IE 7.0 or Office ZR-7 adds multiple monitor capability to Win95, or somebody comes out with a Windows clone that reports itself as 4.0 but handles multiple monitors, or... well, you get the idea. A version-number-based test is a bad idea. As Microsoft tells you right on the GetVersionEx page. And although Windows doesn't have anything quite as spiffy as the Gestalt functions on the Mac, they do have a few functions that let you check for specific features.
Look at GetSystemMetrics(SM_CMONITORS). If the value is 0, that means the OS doesn't have multi-monitor support. If it's 1, the OS supports multiple monitors but the user doesn't have that kind of money. If it's 2 or more, you have to do your tricky multi-monitor code. So, that whole 3-5 lines of code (depending on word wrap) can be replaced by one line: GetSystemMetrics(SM_CMONITORS) > 1
Also, each block of this:
int relativeWidth = (rectRelative.right - rectRelative.left);
if (0 > relativeWidth)
{
relativeWidth = -relativeWidth;
}
can be replaced by this:
int relativeWidth = abs(rectRelative.right - rectRelative.left);
But really, you don't even need that, because even with negative coordinates, the right is still always greater than the left, and the bottom is still always greater than the top, so the width and height are still always positive.
Which means that 26 lines of your function can be replaced by the two lines to calculate xLeft and yTop from the original code sample posted--it'll work exactly the same way, and be slightly more efficient. De-MFC-izing it and making the variables fit your code:
int x = (rectRelative.left + rectRelative.right) / 2 - (rectToMove.right - rectToMove.left) / 2;
int y = (rectRelative.top + rectRelative.bottom) / 2 -
(rectToMove.top - rectToMove.bottom) / 2;
And still, this isn't exactly what CenterWindow should do. Because, if the parent window spans two monitors, the dialog will be stuck in the middle of those two monitors--exactly the problem people were complaining about in the first place.
What you want to do is call MonitorFromWindow(hwndRelative, MONITOR_DEFAULTTONEAREST), then force the entire hwndToMove onto that monitor if there's room (and, ideally, if there's not room, enumerate the monitors looking to see if there is enough room anywhere, etc., and if that fails, provide some fallback that's sufficiently different from the way the Mac works that Steve Jobs won't sue you).
|
|
|
|
 |
|
 |
int x = (rectRelative.left + rectRelative.right) / 2 - (rectToMove.right - rectToMove.left) / 2;
int y = (rectRelative.top + rectRelative.bottom) / 2 -
(rectToMove.top - rectToMove.bottom) / 2;
Would rather be:
int x = abs(rectRelative.left + rectRelative.right) / 2 -
abs(rectToMove.right - rectToMove.left) / 2;
int y = abs(rectRelative.top + rectRelative.bottom) / 2 -
abs(rectToMove.top - rectToMove.bottom) / 2;
to support a single screen situation.
Stilgar.
|
|
|
|
 |
|
 |
Add an OnSize handler to your dialog base class with the following statements:
void CMyProjectBaseDlg::OnSize(UINT nType,
int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if ( m_hWnd)
{
int x = 0;
int y = 0;
CRect rectToCenterOn( 0, 0, 0, 0);
CGLMonitor * pMonitor = NULL ;
CPoint cursor_point ;
GetCursorPos( &cursor_point) ;
pMonitor = GLGlobal::GetMonitor(
cursor_point);
if( pMonitor != NULL)
{
rectToCenterOn = pMonitor->GetRect( );
}
else
{
// nothing defined, center the dialog
CWnd* pMainWnd = AfxGetMainWnd( );
if ( pMainWnd != NULL)
{
pMainWnd->GetWindowRect(&rectToCenterOn);
}
}
if ( ! rectToCenterOn.IsRectNull( ))
{
// find the upper left of where we
// should center to
x = (rectToCenterOn.left +
rectToCenterOn.right) / 2 - cx / 2;
y = (rectToCenterOn.top +
rectToCenterOn.bottom) / 2 - cy / 2;
}
SetWindowPos( NULL, x, y, -1, -1,
SWP_NOZORDER | SWP_NOSIZE |
SWP_SHOWWINDOW);
}
}
(Sorry, the code layout doesn't look nice.)
In my project:
CGLMonitor is a class, which contains all the
relevant data for each monitor.
GLGlobal::GetMonitor is static method which
delivers a pointer to the CGLMonitor object
at the particular mouse pointer.
Why in OnSize()?
I've noticed that the SetWindowPos calls don't always work in OnInitDialog.
Hopefully it will help.
|
|
|
|
 |
|
 |
Thank you so much!!! This is precisely what I needed
|
|
|
|
 |
|
 |
I have implemented something similar for all my projects. What I would like to see now is a similar routine for centering dialogs that is multi-monitor aware. I have several clients with a dual monitor setup, where dialogs all appear centered with half the dialog on each monitor. It would be nice to have a way to auto center on one display or the other.
I've never seen code to handle this. Have you (or anyone else) written something like this
|
|
|
|
 |
|
 |
Is there a way to center the actual form on a CFormView - it always goes to top,left 0/0 - Thanks
|
|
|
|
 |
|
 |
Read this link
http://www.microsoft.com/msj/defaulttop.asp?page=/msj/archive/s1f64.htm
|
|
|
|
 |
|