Skip to content

Commit 47fe9c2

Browse files
committed
System File Chooser: Windows: fixed too small message dialogs (shown from approve callback) (issue #1119)
1 parent 665e794 commit 47fe9c2

2 files changed

Lines changed: 48 additions & 21 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ FlatLaf Change Log
77
- macOS: `Cmd+A` (**Select All**) did not work in file dialog. (issue #1084)
88
- Block Swing input events (mouse, keyboard, etc.) while system file dialog is
99
shown. (issue #1100)
10+
- Windows: Fixed too small message dialogs (shown from approve callback).
11+
(issue #1119)
1012
- macOS: Fixed missing close/iconify/maximize buttons on inactive window, if
1113
system appearance is dark, but application appearance is light. (issue #1032)
1214
- Linux with JetBrains Runtime: Fixed mouse "jumping" to other position when

flatlaf-natives/flatlaf-natives-windows/src/main/cpp/WinMessageDialog.cpp

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ extern void rt_wcscpy( wchar_t* dest, const wchar_t* src );
4040
static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title, LPCWSTR text,
4141
int defaultButton, int buttonCount, LPCWSTR* buttons );
4242
static INT_PTR CALLBACK messageDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
43-
static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen );
44-
static LONG pixel2dluX( LONG px );
45-
static LONG pixel2dluY( LONG px );
46-
static LONG dluX2pixel( LONG dluX );
43+
static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen, LONG baseUnitX );
44+
static LONG pixel2dluX( LONG px, LONG baseUnitX );
45+
static LONG pixel2dluY( LONG px, LONG baseUnitY );
46+
static LONG dluX2pixel( LONG dluX, LONG baseUnitX );
4747
static LPWORD lpwAlign( LPWORD lpIn );
4848

4949

@@ -115,6 +115,12 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
115115
if( !::SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncMetrics, 0 ) )
116116
return NULL;
117117

118+
// printf( "lfMessageFont '%S' %d pt\n", ncMetrics.lfMessageFont.lfFaceName, ncMetrics.lfMessageFont.lfHeight );
119+
// printf( "lfCaptionFont '%S' %d pt\n", ncMetrics.lfCaptionFont.lfFaceName, ncMetrics.lfCaptionFont.lfHeight );
120+
// printf( "lfSmCaptionFont '%S' %d pt\n", ncMetrics.lfSmCaptionFont.lfFaceName, ncMetrics.lfSmCaptionFont.lfHeight );
121+
// printf( "lfMenuFont '%S' %d pt\n", ncMetrics.lfMenuFont.lfFaceName, ncMetrics.lfMenuFont.lfHeight );
122+
// printf( "lfStatusFont '%S' %d pt\n", ncMetrics.lfStatusFont.lfFaceName, ncMetrics.lfStatusFont.lfHeight );
123+
118124
// create DC to use message font
119125
HDC hdcOwner = ::GetDC( owner );
120126
HDC hdc = ::CreateCompatibleDC( hdcOwner );
@@ -134,6 +140,18 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
134140
return NULL;
135141
}
136142

143+
// get dialog base unit for message font
144+
TEXTMETRIC tm;
145+
if( !::GetTextMetrics( hdc, &tm ) ) {
146+
::DeleteDC( hdc );
147+
::DeleteObject( hfont );
148+
return NULL;
149+
}
150+
LONG baseUnitX = tm.tmAveCharWidth;
151+
LONG baseUnitY = tm.tmHeight;
152+
// printf( "baseUnit X/Y %d %d for message font\n", baseUnitX, baseUnitY );
153+
// printf( "baseUnit X/Y %d %d for system font\n", LOWORD( ::GetDialogBaseUnits() ), HIWORD( ::GetDialogBaseUnits() ) );
154+
137155
//---- calculate layout (in DLUs) ----
138156

139157
// layout icon
@@ -148,8 +166,9 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
148166
}
149167
int ix = INSETS_LEFT;
150168
int iy = INSETS_TOP;
151-
int iw = pixel2dluX( ::GetSystemMetrics( SM_CXICON ) );
152-
int ih = pixel2dluY( ::GetSystemMetrics( SM_CYICON ) );
169+
int iw = pixel2dluX( ::GetSystemMetrics( SM_CXICON ), baseUnitX );
170+
int ih = pixel2dluY( ::GetSystemMetrics( SM_CYICON ), baseUnitY );
171+
// printf( "icon size: %d,%d px %d,%d dlu\n", ::GetSystemMetrics( SM_CXICON ), ::GetSystemMetrics( SM_CYICON ), iw, ih );
153172

154173
// layout text
155174
int tx = ix + (icon != NULL ? iw + ICON_TEXT_GAP : 0);
@@ -169,16 +188,17 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
169188
int lineLen = t - lineStart;
170189
int fit = 0;
171190
SIZE size{ 0 };
172-
if( !::GetTextExtentExPoint( hdc, lineStart, lineLen, dluX2pixel( LABEL_MAX_WIDTH ), &fit, NULL, &size ) )
191+
if( !::GetTextExtentExPoint( hdc, lineStart, lineLen, dluX2pixel( LABEL_MAX_WIDTH, baseUnitX ), &fit, NULL, &size ) )
173192
break;
193+
// printf( "text extend: fit %d chars size %d,%d px text: %d '%S'\n", fit, size.cx, size.cy, lineLen, lineStart );
174194

175195
if( fit < lineLen ) {
176196
// wrap too long line --> try to wrap at space character
177197
bool wrapped = false;
178198
for( LPWSTR t2 = lineStart + fit - 1; t2 > lineStart; t2-- ) {
179199
if( *t2 == ' ' || *t2 == '\t' ) {
180200
*t2 = '\n';
181-
int w = textLengthAsDLUs( hdc, lineStart, t2 - lineStart );
201+
int w = textLengthAsDLUs( hdc, lineStart, t2 - lineStart, baseUnitX );
182202
tw = max( tw, w );
183203
th += LABEL_HEIGHT;
184204

@@ -192,7 +212,7 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
192212
if( !wrapped ) {
193213
// not able to wrap at word --> break long word
194214
int breakIndex = (lineStart + fit) - wrappedText;
195-
int w = textLengthAsDLUs( hdc, lineStart, breakIndex );
215+
int w = textLengthAsDLUs( hdc, lineStart, fit, baseUnitX );
196216
tw = max( tw, w );
197217
th += LABEL_HEIGHT;
198218

@@ -213,7 +233,7 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
213233
}
214234
} else {
215235
// line fits into LABEL_MAX_WIDTH
216-
int w = pixel2dluX( size.cx );
236+
int w = pixel2dluX( size.cx, baseUnitX );
217237
tw = max( tw, w );
218238
th += LABEL_HEIGHT;
219239
lineStart = t + 1;
@@ -222,16 +242,18 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
222242
if( *t == 0 )
223243
break;
224244
}
245+
// printf( "tw %d dlu / %d px th %d dlu / %d px\n", tw, dluX2pixel( tw, baseUnitX ), th, MulDiv( th, baseUnitY, 8 ) );
225246
tw = min( max( tw, LABEL_MIN_WIDTH ), LABEL_MAX_WIDTH );
226247
th = max( th, LABEL_HEIGHT );
248+
// printf( "tw %d dlu / %d px th %d dlu / %d px\n", tw, dluX2pixel( tw, baseUnitX ), th, MulDiv( th, baseUnitY, 8 ) );
227249
if( icon != NULL && th < ih )
228250
ty += (ih - th) / 2; // vertically center text
229251

230252
// layout buttons
231253
int* bw = new int[buttonCount];
232254
int buttonTotalWidth = BUTTON_GAP * (buttonCount - 1);
233255
for( int i = 0; i < buttonCount; i++ ) {
234-
int w = textLengthAsDLUs( hdc, buttons[i], -1 ) + 16;
256+
int w = textLengthAsDLUs( hdc, buttons[i], -1, baseUnitX ) + 16;
235257
bw[i] = max( BUTTON_WIDTH, w );
236258
buttonTotalWidth += bw[i];
237259
}
@@ -241,12 +263,13 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
241263
int dy = 0;
242264
int dw = max( tx + tw + INSETS_RIGHT, BUTTON_LEFT_RIGHT_GAP + buttonTotalWidth + BUTTON_LEFT_RIGHT_GAP );
243265
int dh = max( iy + ih, ty + th ) + BUTTON_TOP_GAP + BUTTON_HEIGHT + INSETS_BOTTOM;
266+
// printf( "dw %d dlu / %d px dh %d dlu / %d px\n", dw, dluX2pixel( dw, baseUnitX ), dh, MulDiv( th, baseUnitY, 8 ) );
244267

245268
// center dialog in owner
246269
RECT ownerRect{ 0 };
247270
if( ::GetClientRect( owner, &ownerRect ) ) {
248-
dx = (pixel2dluX( ownerRect.right - ownerRect.left ) - dw) / 2;
249-
dy = (pixel2dluY( ownerRect.bottom - ownerRect.top ) - dh) / 2;
271+
dx = (pixel2dluX( ownerRect.right - ownerRect.left, baseUnitX ) - dw) / 2;
272+
dy = (pixel2dluY( ownerRect.bottom - ownerRect.top, baseUnitY ) - dh) / 2;
250273
}
251274

252275
// layout button area
@@ -258,6 +281,7 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
258281
? -MulDiv( ncMetrics.lfMessageFont.lfHeight, 72, ::GetDeviceCaps( hdc, LOGPIXELSY ) )
259282
: ncMetrics.lfMessageFont.lfHeight;
260283
LPCWSTR fontFaceName = ncMetrics.lfMessageFont.lfFaceName;
284+
// printf( "font '%S' %d pt\n", fontFaceName, fontPointSize );
261285

262286
// delete DC and font
263287
::DeleteDC( hdc );
@@ -396,22 +420,23 @@ static INT_PTR CALLBACK messageDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam,
396420
return FALSE;
397421
}
398422

399-
static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen ) {
423+
static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen, LONG baseUnitX ) {
400424
SIZE size{ 0 };
401425
::GetTextExtentPoint32( hdc, str, (strLen >= 0) ? strLen : rt_wcslen( str ), &size );
402-
return pixel2dluX( size.cx );
426+
// printf( "textLengthAsDLUs: %d px %d dlu text: %d '%S'\n", size.cx, pixel2dluX( size.cx, baseUnitX ), strLen, str );
427+
return pixel2dluX( size.cx, baseUnitX );
403428
}
404429

405-
static LONG pixel2dluX( LONG px ) {
406-
return MulDiv( px, 4, LOWORD( ::GetDialogBaseUnits() ) );
430+
static LONG pixel2dluX( LONG px, LONG baseUnitX ) {
431+
return MulDiv( px, 4, baseUnitX );
407432
}
408433

409-
static LONG pixel2dluY( LONG py ) {
410-
return MulDiv( py, 8, HIWORD( ::GetDialogBaseUnits() ) );
434+
static LONG pixel2dluY( LONG py, LONG baseUnitY ) {
435+
return MulDiv( py, 8, baseUnitY );
411436
}
412437

413-
static LONG dluX2pixel( LONG dluX ) {
414-
return MulDiv( dluX, LOWORD( ::GetDialogBaseUnits() ), 4 );
438+
static LONG dluX2pixel( LONG dluX, LONG baseUnitX ) {
439+
return MulDiv( dluX, baseUnitX, 4 );
415440
}
416441

417442
static LPWORD lpwAlign( LPWORD lpIn ) {

0 commit comments

Comments
 (0)