Win32: Fix print dialog custom widget measurement

This commit is contained in:
Luca Bacci 2021-11-15 11:51:43 +01:00
parent a174568ef9
commit 1650b4b205
No known key found for this signature in database
GPG Key ID: 8E3C8D989C98883D
2 changed files with 110 additions and 35 deletions

View File

@ -47,6 +47,29 @@
#include "gtkwin32embedwidget.h" #include "gtkwin32embedwidget.h"
#include "gtkprivate.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 MAX_PAGE_RANGES 20
#define STATUS_POLLING_TIME 2000 #define STATUS_POLLING_TIME 2000
@ -1461,7 +1484,12 @@ pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
} }
else 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; op_win32 = op->priv->platform_data;
return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget), 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; return FALSE;
} }
static HPROPSHEETPAGE static INT_PTR CALLBACK
create_application_page (GtkPrintOperation *op) measure_dialog_procedure (HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{ {
HPROPSHEETPAGE hpage; return FALSE;
PROPSHEETPAGEW page; }
DLGTEMPLATE *template;
static HPROPSHEETPAGE
create_application_page (GtkPrintOperation *op,
HWND hwndOwner,
int scale)
{
const LONG DBU_DEFAULT = GetDialogBaseUnits ();
int dbu_x = LOWORD (DBU_DEFAULT);
int dbu_y = HIWORD (DBU_DEFAULT);
HWND measure_dialog = NULL;
HGLOBAL htemplate; HGLOBAL htemplate;
LONG base_units; DLGTEMPLATEEX *template;
WORD baseunitX, baseunitY; PROPSHEETPAGEW page;
WORD *array; HPROPSHEETPAGE hpage;
GtkRequisition requisition; GtkRequisition requisition;
const char *tab_label; const char *tab_label = 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);
htemplate = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (DLGTEMPLATEEX));
template = GlobalLock (htemplate);
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 */ /* Make the template the size of the custom widget size request */
gtk_widget_get_preferred_size (op->priv->custom_widget, template->exStyle |= WS_EX_CONTROLPARENT;
&requisition, NULL); 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;
base_units = GetDialogBaseUnits ();
baseunitX = LOWORD (base_units);
baseunitY = HIWORD (base_units);
htemplate = GlobalAlloc (GMEM_MOVEABLE,
sizeof (DLGTEMPLATE) + sizeof (WORD) * 3);
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 */
memset (&page, 0, sizeof (page)); memset (&page, 0, sizeof (page));
page.dwSize = sizeof (page); page.dwSize = sizeof (page);
page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE; page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
@ -1731,6 +1799,7 @@ gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
GtkPrintOperationPrivate *priv; GtkPrintOperationPrivate *priv;
IPrintDialogCallback *callback; IPrintDialogCallback *callback;
HPROPSHEETPAGE prop_page; HPROPSHEETPAGE prop_page;
int scale = 1;
static volatile gsize common_controls_initialized = 0; static volatile gsize common_controls_initialized = 0;
if (g_once_init_enter (&common_controls_initialized)) if (g_once_init_enter (&common_controls_initialized))
@ -1762,10 +1831,15 @@ gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
if (parent == NULL) if (parent == NULL)
{ {
invisible = gtk_invisible_new (); invisible = gtk_invisible_new ();
parentHWnd = get_parent_hwnd (invisible); 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)); printdlgex = (LPPRINTDLGEXW)GlobalAlloc (GPTR, sizeof (PRINTDLGEXW));
if (!printdlgex) if (!printdlgex)
@ -1817,7 +1891,7 @@ gtk_print_operation_run_with_dialog (GtkPrintOperation *op,
g_signal_emit_by_name (op, "create-custom-widget", g_signal_emit_by_name (op, "create-custom-widget",
&op->priv->custom_widget); &op->priv->custom_widget);
if (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->nPropertyPages = 1;
printdlgex->lphPropertyPages = &prop_page; printdlgex->lphPropertyPages = &prop_page;
} else { } else {

View File

@ -85,6 +85,7 @@ gtk_win32_embed_widget_init (GtkWin32EmbedWidget *embed_widget)
G_GNUC_BEGIN_IGNORE_DEPRECATIONS; G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
gtk_container_set_resize_mode (GTK_CONTAINER (embed_widget), GTK_RESIZE_QUEUE); gtk_container_set_resize_mode (GTK_CONTAINER (embed_widget), GTK_RESIZE_QUEUE);
G_GNUC_END_IGNORE_DEPRECATIONS; G_GNUC_END_IGNORE_DEPRECATIONS;
gtk_window_set_decorated (GTK_WINDOW (embed_widget), FALSE);
} }
GtkWidget* GtkWidget*