Merge branch 'gdk-win32-custom-print-dialog-widget-measurement' into 'gtk-3-24'

Fix measurement of custom widget in win32 print dialog

See merge request GNOME/gtk!4159
This commit is contained in:
Luca Bacci 2021-11-18 19:02:58 +00:00
commit 661f23d337
2 changed files with 110 additions and 35 deletions

View File

@ -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 HPROPSHEETPAGE
create_application_page (GtkPrintOperation *op)
static INT_PTR CALLBACK
measure_dialog_procedure (HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
HPROPSHEETPAGE hpage;
PROPSHEETPAGEW page;
DLGTEMPLATE *template;
return FALSE;
}
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;
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;
/* 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 */
gtk_widget_get_preferred_size (op->priv->custom_widget,
&requisition, NULL);
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;
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));
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 {

View File

@ -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*