[gtk/gtk-3-24: 1/2] Win32: Fix print dialog custom widget measurement




commit 1650b4b205191609b5e79393ca07257fa6aa8bca
Author: Luca Bacci <luca bacci982 gmail com>
Date:   Mon Nov 15 11:51:43 2021 +0100

    Win32: Fix print dialog custom widget measurement

 gtk/gtkprintoperation-win32.c | 142 ++++++++++++++++++++++++++++++++----------
 gtk/gtkwin32embedwidget.c     |   1 +
 2 files changed, 109 insertions(+), 34 deletions(-)
---
diff --git a/gtk/gtkprintoperation-win32.c b/gtk/gtkprintoperation-win32.c
index b3f9a21cb2..abd4f7de95 100644
--- a/gtk/gtkprintoperation-win32.c
+++ b/gtk/gtkprintoperation-win32.c
@@ -47,6 +47,29 @@
 #include "gtkwin32embedwidget.h"
 #include "gtkprivate.h"
 
+#include <pshpack1.h>
+typedef struct {
+  WORD      dlgVer;
+  WORD      signature;
+  DWORD     helpID;
+  DWORD     exStyle;
+  DWORD     style;
+  WORD      cDlgItems;
+  short     x;
+  short     y;
+  short     cx;
+  short     cy;
+  short     menu;
+  short     windowClass;
+  WCHAR     title;
+  WORD      pointsize;
+  WORD      weight;
+  BYTE      italic;
+  BYTE      charset;
+  WCHAR     typeface[LF_FACESIZE];
+} DLGTEMPLATEEX;
+#include <poppack.h>
+
 #define MAX_PAGE_RANGES 20
 #define STATUS_POLLING_TIME 2000
 
@@ -1461,7 +1484,12 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
     }
   else 
     {
-      op = GTK_PRINT_OPERATION (GetWindowLongPtrW (wnd, GWLP_USERDATA));
+      gpointer user_data = GetWindowLongPtrW (wnd, GWLP_USERDATA);
+
+      if (!user_data)
+        return FALSE;
+
+      op = GTK_PRINT_OPERATION (user_data);
       op_win32 = op->priv->platform_data;
 
       return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
@@ -1471,43 +1499,83 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
   return FALSE;
 }
 
+static INT_PTR CALLBACK
+measure_dialog_procedure (HWND hwnd,
+                          UINT uMsg,
+                          WPARAM wParam,
+                          LPARAM lParam)
+{
+  return FALSE;
+}
+
 static HPROPSHEETPAGE
-create_application_page (GtkPrintOperation *op)
+create_application_page (GtkPrintOperation *op,
+                         HWND hwndOwner,
+                         int scale)
 {
-  HPROPSHEETPAGE hpage;
-  PROPSHEETPAGEW page;
-  DLGTEMPLATE *template;
+  const LONG DBU_DEFAULT = GetDialogBaseUnits ();
+  int dbu_x = LOWORD (DBU_DEFAULT);
+  int dbu_y = HIWORD (DBU_DEFAULT);
+  HWND measure_dialog = NULL;
   HGLOBAL htemplate;
-  LONG base_units;
-  WORD baseunitX, baseunitY;
-  WORD *array;
+  DLGTEMPLATEEX *template;
+  PROPSHEETPAGEW page;
+  HPROPSHEETPAGE hpage;
   GtkRequisition requisition;
-  const char *tab_label;
+  const char *tab_label = NULL;
 
-  /* Make the template the size of the custom widget size request */
-  gtk_widget_get_preferred_size (op->priv->custom_widget,
-                                 &requisition, NULL);
+  /* Widget must be visible to measure its size */
+  gtk_widget_show (op->priv->custom_widget);
+  gtk_widget_get_preferred_size (op->priv->custom_widget, &requisition, NULL);
 
-  base_units = GetDialogBaseUnits ();
-  baseunitX = LOWORD (base_units);
-  baseunitY = HIWORD (base_units);
-  
-  htemplate = GlobalAlloc (GMEM_MOVEABLE, 
-                          sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
+  htemplate = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (DLGTEMPLATEEX));
   template = GlobalLock (htemplate);
-  template->style = WS_CHILDWINDOW | DS_CONTROL;
-  template->dwExtendedStyle = WS_EX_CONTROLPARENT;
-  template->cdit = 0;
-  template->x = MulDiv (0, 4, baseunitX);
-  template->y = MulDiv (0, 8, baseunitY);
-  template->cx = MulDiv (requisition.width, 4, baseunitX);
-  template->cy = MulDiv (requisition.height, 8, baseunitY);
-  
-  array = (WORD *) (template+1);
-  *array++ = 0; /* menu */
-  *array++ = 0; /* class */
-  *array++ = 0; /* title */
-  
+  template->dlgVer = 1;
+  template->signature = 0xFFFF;
+  template->helpID = 0;
+  template->exStyle = 0;
+  template->style = DS_SHELLFONT;
+  template->cDlgItems = 0;
+  template->x = 0;
+  template->y = 0;
+  template->cx = 10;
+  template->cy = 10;
+  template->menu = 0;
+  template->windowClass = 0;
+  template->title = 0;
+  template->pointsize = 8;
+  template->weight = FW_NORMAL;
+  template->italic = FALSE;
+  template->charset = DEFAULT_CHARSET;
+  wcscpy_s (template->typeface, LF_FACESIZE, L"MS Shell Dlg");
+
+  /* Create an invisible dialog to measure dialog base units */
+  measure_dialog = CreateDialogIndirectW (NULL, template, hwndOwner, measure_dialog_procedure);
+  if (!measure_dialog)
+    g_warning ("CreateDialogIndirectW failed");
+  else
+    {
+      RECT rect;
+
+      SetRect (&rect, 0, 0, 4, 8);
+      if (!MapDialogRect (measure_dialog, &rect))
+        g_warning ("MapDialogRect failed");
+      else
+        {
+          dbu_x = rect.right - rect.left;
+          dbu_y = rect.bottom - rect.top;
+        }
+
+      DestroyWindow (measure_dialog);
+      measure_dialog = NULL;
+    }
+
+  /* Make the template the size of the custom widget size request */
+  template->exStyle |= WS_EX_CONTROLPARENT;
+  template->style |= WS_CHILD | DS_CONTROL;
+  template->cx = (requisition.width * scale * 4.0) / dbu_x + 1;
+  template->cy = (requisition.height * scale * 8.0) / dbu_y + 1;
+
   memset (&page, 0, sizeof (page));
   page.dwSize = sizeof (page);
   page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
@@ -1731,6 +1799,7 @@ gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
   GtkPrintOperationPrivate *priv;
   IPrintDialogCallback *callback;
   HPROPSHEETPAGE prop_page;
+  int scale = 1;
   static volatile gsize common_controls_initialized = 0;
 
   if (g_once_init_enter (&common_controls_initialized))
@@ -1762,10 +1831,15 @@ gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
   if (parent == NULL)
     {
       invisible = gtk_invisible_new ();
+
       parentHWnd = get_parent_hwnd (invisible);
+      scale = gtk_widget_get_scale_factor (invisible);
+    }
+  else
+    {
+      parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
+      scale = gtk_widget_get_scale_factor (GTK_WIDGET (parent));
     }
-  else 
-    parentHWnd = get_parent_hwnd (GTK_WIDGET (parent));
 
   printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
   if (!printdlgex)
@@ -1817,7 +1891,7 @@ gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
   g_signal_emit_by_name (op, "create-custom-widget",
                         &op->priv->custom_widget);
   if (op->priv->custom_widget) {
-    prop_page = create_application_page (op);
+    prop_page = create_application_page (op, parentHWnd, scale);
     printdlgex->nPropertyPages = 1;
     printdlgex->lphPropertyPages = &prop_page;
   } else {
diff --git a/gtk/gtkwin32embedwidget.c b/gtk/gtkwin32embedwidget.c
index c4e6aff897..619a459c94 100644
--- a/gtk/gtkwin32embedwidget.c
+++ b/gtk/gtkwin32embedwidget.c
@@ -85,6 +85,7 @@ gtk_win32_embed_widget_init (GtkWin32EmbedWidget *embed_widget)
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
   gtk_container_set_resize_mode (GTK_CONTAINER (embed_widget), GTK_RESIZE_QUEUE);
 G_GNUC_END_IGNORE_DEPRECATIONS;
+  gtk_window_set_decorated (GTK_WINDOW (embed_widget), FALSE);
 }
 
 GtkWidget*


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]