Alexandre Julliard : user: Take multiple monitors into account when placing a dialog.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Oct 23 10:00:59 CDT 2006


Module: wine
Branch: master
Commit: ca58c8179fef4f89fbc304ba8cbad86432c8dfca
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ca58c8179fef4f89fbc304ba8cbad86432c8dfca

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Oct 23 14:04:12 2006 +0200

user: Take multiple monitors into account when placing a dialog.

---

 dlls/user/dialog.c   |   63 ++++++++++++++++++++++++++++++++++----------------
 dlls/user/dialog16.c |   61 ++++++++++++++++++++++++++++++++++--------------
 2 files changed, 86 insertions(+), 38 deletions(-)

diff --git a/dlls/user/dialog.c b/dlls/user/dialog.c
index 8934a54..d43247c 100644
--- a/dlls/user/dialog.c
+++ b/dlls/user/dialog.c
@@ -463,6 +463,8 @@ static HWND DIALOG_CreateIndirect( HINST
 {
     HWND hwnd;
     RECT rect;
+    POINT pos;
+    SIZE size;
     DLG_TEMPLATE template;
     DIALOGINFO * dlgInfo = NULL;
     DWORD units = GetDialogBaseUnits();
@@ -524,40 +526,63 @@ static HWND DIALOG_CreateIndirect( HINST
     if (template.style & DS_CONTROL)
         template.exStyle |= WS_EX_CONTROLPARENT;
     AdjustWindowRectEx( &rect, template.style, (hMenu != 0), template.exStyle );
-    rect.right -= rect.left;
-    rect.bottom -= rect.top;
+    pos.x = rect.left;
+    pos.y = rect.top;
+    size.cx = rect.right - rect.left;
+    size.cy = rect.bottom - rect.top;
 
     if (template.x == CW_USEDEFAULT16)
     {
-        rect.left = rect.top = CW_USEDEFAULT;
+        pos.x = pos.y = CW_USEDEFAULT;
     }
     else
     {
+        HMONITOR monitor = 0;
+        MONITORINFO mon_info;
+
+        mon_info.cbSize = sizeof(mon_info);
         if (template.style & DS_CENTER)
         {
-            rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
-            rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
+            if (!(monitor = MonitorFromWindow( owner ? owner : GetActiveWindow(),
+                                               MONITOR_DEFAULTTOPRIMARY )))
+            {
+                pos.x = pos.y = 0;  /* default to primary monitor */
+                monitor = MonitorFromPoint( pos, MONITOR_DEFAULTTOPRIMARY );
+            }
+            GetMonitorInfoW( monitor, &mon_info );
+            pos.x = (mon_info.rcWork.left + mon_info.rcWork.right - size.cx) / 2;
+            pos.y = (mon_info.rcWork.top + mon_info.rcWork.bottom - size.cy) / 2;
+        }
+        else if (template.style & DS_CENTERMOUSE)
+        {
+            GetCursorPos( &pos );
+            monitor = MonitorFromPoint( pos, MONITOR_DEFAULTTOPRIMARY );
+            GetMonitorInfoW( monitor, &mon_info );
         }
         else
         {
-            rect.left += MulDiv(template.x, xBaseUnit, 4);
-            rect.top += MulDiv(template.y, yBaseUnit, 8);
+            pos.x += MulDiv(template.x, xBaseUnit, 4);
+            pos.y += MulDiv(template.y, yBaseUnit, 8);
+            if (!(template.style & (WS_CHILD|DS_ABSALIGN))) ClientToScreen( owner, &pos );
         }
         if ( !(template.style & WS_CHILD) )
         {
             INT dX, dY;
 
-            if( !(template.style & DS_ABSALIGN) )
-                ClientToScreen( owner, (POINT *)&rect );
-
             /* try to fit it into the desktop */
 
-            if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
-                 - GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
-            if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
-                 - GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
-            if( rect.left < 0 ) rect.left = 0;
-            if( rect.top < 0 ) rect.top = 0;
+            if (!monitor)
+            {
+                SetRect( &rect, pos.x, pos.y, pos.x + size.cx, pos.y + size.cy );
+                monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
+                GetMonitorInfoW( monitor, &mon_info );
+            }
+            if ((dX = pos.x + size.cx + GetSystemMetrics(SM_CXDLGFRAME) - mon_info.rcWork.right) > 0)
+                pos.x -= dX;
+            if ((dY = pos.y + size.cy + GetSystemMetrics(SM_CYDLGFRAME) - mon_info.rcWork.bottom) > 0)
+                pos.y -= dY;
+            if( pos.x < mon_info.rcWork.left ) pos.x = mon_info.rcWork.left;
+            if( pos.y < mon_info.rcWork.top ) pos.y = mon_info.rcWork.top;
         }
     }
 
@@ -570,8 +595,7 @@ static HWND DIALOG_CreateIndirect( HINST
     if (unicode)
     {
         hwnd = CreateWindowExW(template.exStyle, template.className, template.caption,
-                               template.style & ~WS_VISIBLE,
-                               rect.left, rect.top, rect.right, rect.bottom,
+                               template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy,
                                owner, hMenu, hInst, NULL );
     }
     else
@@ -592,8 +616,7 @@ static HWND DIALOG_CreateIndirect( HINST
             WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption, len, NULL, NULL );
         }
         hwnd = CreateWindowExA(template.exStyle, class, caption,
-                               template.style & ~WS_VISIBLE,
-                               rect.left, rect.top, rect.right, rect.bottom,
+                               template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy,
                                owner, hMenu, hInst, NULL );
         if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
         if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
diff --git a/dlls/user/dialog16.c b/dlls/user/dialog16.c
index c7bb73f..2df59fc 100644
--- a/dlls/user/dialog16.c
+++ b/dlls/user/dialog16.c
@@ -290,6 +290,8 @@ static HWND DIALOG_CreateIndirect16( HIN
 {
     HWND hwnd;
     RECT rect;
+    POINT pos;
+    SIZE size;
     WND * wndPtr;
     DLG_TEMPLATE template;
     DIALOGINFO * dlgInfo;
@@ -356,40 +358,63 @@ static HWND DIALOG_CreateIndirect16( HIN
     rect.bottom =  MulDiv(template.cy, dlgInfo->yBaseUnit, 8);
     if (template.style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME;
     AdjustWindowRectEx( &rect, template.style, (dlgInfo->hMenu != 0), exStyle );
-    rect.right -= rect.left;
-    rect.bottom -= rect.top;
+    pos.x = rect.left;
+    pos.y = rect.top;
+    size.cx = rect.right - rect.left;
+    size.cy = rect.bottom - rect.top;
 
     if (template.x == CW_USEDEFAULT16)
     {
-        rect.left = rect.top = CW_USEDEFAULT16;
+        pos.x = pos.y = CW_USEDEFAULT16;
     }
     else
     {
+        HMONITOR monitor = 0;
+        MONITORINFO mon_info;
+
+        mon_info.cbSize = sizeof(mon_info);
         if (template.style & DS_CENTER)
         {
-            rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
-            rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
+            if (!(monitor = MonitorFromWindow( owner ? owner : GetActiveWindow(),
+                                               MONITOR_DEFAULTTOPRIMARY )))
+            {
+                pos.x = pos.y = 0;  /* default to primary monitor */
+                monitor = MonitorFromPoint( pos, MONITOR_DEFAULTTOPRIMARY );
+            }
+            GetMonitorInfoW( monitor, &mon_info );
+            pos.x = (mon_info.rcWork.left + mon_info.rcWork.right - size.cx) / 2;
+            pos.y = (mon_info.rcWork.top + mon_info.rcWork.bottom - size.cy) / 2;
+        }
+        else if (template.style & DS_CENTERMOUSE)
+        {
+            GetCursorPos( &pos );
+            monitor = MonitorFromPoint( pos, MONITOR_DEFAULTTOPRIMARY );
+            GetMonitorInfoW( monitor, &mon_info );
         }
         else
         {
-            rect.left += MulDiv(template.x, dlgInfo->xBaseUnit, 4);
-            rect.top += MulDiv(template.y, dlgInfo->yBaseUnit, 8);
+            pos.x += MulDiv(template.x, dlgInfo->xBaseUnit, 4);
+            pos.y += MulDiv(template.y, dlgInfo->yBaseUnit, 8);
+            if (!(template.style & (WS_CHILD|DS_ABSALIGN))) ClientToScreen( owner, &pos );
         }
         if ( !(template.style & WS_CHILD) )
         {
-            INT16 dX, dY;
-
-            if( !(template.style & DS_ABSALIGN) )
-                ClientToScreen( owner, (POINT *)&rect );
+            INT dX, dY;
 
             /* try to fit it into the desktop */
 
-            if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
-                 - GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
-            if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
-                 - GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
-            if( rect.left < 0 ) rect.left = 0;
-            if( rect.top < 0 ) rect.top = 0;
+            if (!monitor)
+            {
+                SetRect( &rect, pos.x, pos.y, pos.x + size.cx, pos.y + size.cy );
+                monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
+                GetMonitorInfoW( monitor, &mon_info );
+            }
+            if ((dX = pos.x + size.cx + GetSystemMetrics(SM_CXDLGFRAME) - mon_info.rcWork.right) > 0)
+                pos.x -= dX;
+            if ((dY = pos.y + size.cy + GetSystemMetrics(SM_CYDLGFRAME) - mon_info.rcWork.bottom) > 0)
+                pos.y -= dY;
+            if( pos.x < mon_info.rcWork.left ) pos.x = mon_info.rcWork.left;
+            if( pos.y < mon_info.rcWork.top ) pos.y = mon_info.rcWork.top;
         }
     }
 
@@ -401,7 +426,7 @@ static HWND DIALOG_CreateIndirect16( HIN
 
     hwnd = WIN_Handle32( CreateWindowEx16(exStyle, template.className,
                                           template.caption, template.style & ~WS_VISIBLE,
-                                          rect.left, rect.top, rect.right, rect.bottom,
+                                          pos.x, pos.y, size.cx, size.cy,
                                           HWND_16(owner), HMENU_16(dlgInfo->hMenu),
                                           hInst, NULL ));
     if (!hwnd)




More information about the wine-cvs mailing list