Commit 229d9a6e authored by Rein Klazes's avatar Rein Klazes Committed by Alexandre Julliard

comdlg32: Fix problems in calculation of the size of a file dialog.

parent e5e40ef4
......@@ -277,6 +277,9 @@ static BOOL GetFileName95(FileOpenDlgInfos *fodInfos)
fodInfos->sizedlg.cx = fodInfos->sizedlg.cy = 0;
fodInfos->initial_size.x = fodInfos->initial_size.y = 0;
}
else
((LPDLGTEMPLATEW)template)->style &= ~WS_SIZEBOX;
/* old style hook messages */
if (IsHooked(fodInfos))
......@@ -554,13 +557,14 @@ static BOOL COMDLG32_GetDisplayNameOf(LPCITEMIDLIST pidl, LPWSTR pwszPath) {
/***********************************************************************
* ArrangeCtrlPositions [internal]
*
* NOTE: Do not change anything here without a lot of testing.
* NOTE: Make sure to add testcases for any changes made here.
*/
static void ArrangeCtrlPositions(HWND hwndChildDlg, HWND hwndParentDlg, BOOL hide_help)
{
HWND hwndChild, hwndStc32;
RECT rectParent, rectChild, rectStc32;
INT help_fixup = 0, child_height_fixup = 0, child_width_fixup = 0;
INT help_fixup = 0;
int chgx, chgy;
/* Take into account if open as read only checkbox and help button
* are hidden
......@@ -623,24 +627,16 @@ static void ArrangeCtrlPositions(HWND hwndChildDlg, HWND hwndParentDlg, BOOL hid
/* move only if stc32 exist */
if (hwndStc32 && rectChild.left > rectStc32.right)
{
LONG old_left = rectChild.left;
/* move to the right of visible controls of the parent dialog */
rectChild.left += rectParent.right;
rectChild.left -= rectStc32.right;
child_width_fixup = rectChild.left - old_left;
}
/* move even if stc32 doesn't exist */
if (rectChild.top >= rectStc32.bottom)
{
LONG old_top = rectChild.top;
/* move below visible controls of the parent dialog */
rectChild.top += rectParent.bottom;
rectChild.top -= rectStc32.bottom - rectStc32.top;
child_height_fixup = rectChild.top - old_top;
}
SetWindowPos(hwndChild, 0, rectChild.left, rectChild.top,
......@@ -675,50 +671,36 @@ static void ArrangeCtrlPositions(HWND hwndChildDlg, HWND hwndParentDlg, BOOL hid
/* here we have to use original parent size */
GetClientRect(hwndParentDlg, &rectParent);
GetClientRect(hwndChildDlg, &rectChild);
TRACE( "parent %s child %s stc32 %s\n", wine_dbgstr_rect( &rectParent),
wine_dbgstr_rect( &rectChild), wine_dbgstr_rect( &rectStc32));
if (hwndStc32)
{
rectChild.right += child_width_fixup;
rectChild.bottom += child_height_fixup;
if (rectParent.right > rectChild.right)
{
rectParent.right += rectChild.right;
rectParent.right -= rectStc32.right - rectStc32.left;
}
/* width */
if (rectParent.right > rectStc32.right - rectStc32.left)
chgx = rectChild.right - ( rectStc32.right - rectStc32.left);
else
{
rectParent.right = rectChild.right;
}
if (rectParent.bottom > rectChild.bottom)
{
rectParent.bottom += rectChild.bottom;
rectParent.bottom -= rectStc32.bottom - rectStc32.top;
}
chgx = rectChild.right - rectParent.right;
/* height */
if (rectParent.bottom > rectStc32.bottom - rectStc32.top)
chgy = rectChild.bottom - ( rectStc32.bottom - rectStc32.top) - help_fixup;
else
{
/* child dialog is higher, unconditionally set new dialog
* height to its size (help_fixup will be subtracted below)
/* Unconditionally set new dialog
* height to that of the child
*/
rectParent.bottom = rectChild.bottom + help_fixup;
}
chgy = rectChild.bottom - rectParent.bottom;
}
else
{
rectParent.bottom += rectChild.bottom;
chgx = 0;
chgy = rectChild.bottom - help_fixup;
}
/* finally use fixed parent size */
rectParent.bottom -= help_fixup;
/* set the size of the parent dialog */
AdjustWindowRectEx(&rectParent, GetWindowLongW(hwndParentDlg, GWL_STYLE),
FALSE, GetWindowLongW(hwndParentDlg, GWL_EXSTYLE));
GetWindowRect(hwndParentDlg, &rectParent);
SetWindowPos(hwndParentDlg, 0,
0, 0,
rectParent.right - rectParent.left,
rectParent.bottom - rectParent.top,
rectParent.right - rectParent.left + chgx,
rectParent.bottom - rectParent.top + chgy,
SWP_NOMOVE | SWP_NOZORDER);
}
......
......@@ -664,11 +664,209 @@ static void test_ok(void)
ok( ret, "Failed to delete temporary file %s err %d\n", tmpfilename, GetLastError());
}
/* test arranging with a custom template */
typedef struct {
int x, y; /* left, top coordinates */
int cx, cy; /* width and height */
} posz;
static struct {
int nrcontrols; /* 0: no controls, 1: just the stc32 control 2: with button */
posz poszDlg;
posz poszStc32;
posz poszBtn;
DWORD ofnflags;
} arrange_tests[] = {
/* do not change the first two cases: used to get the uncustomized sizes */
{ 0, {0},{0},{0},0 },
{ 0, {0},{0},{0}, OFN_SHOWHELP},
/* two tests with just a subdialog, no controls */
{ 0, {0, 0, 316, 76},{0},{0},0 },
{ 0, {0, 0, 100, 76},{0},{0}, OFN_SHOWHELP},
/* now with a control with id stc32 */
{ 1, {0, 0, 316, 76} ,{0, 0, 204, 76,},{0},0 }, /* bug #17748*/
{ 1, {0, 0, 316, 76} ,{0, 0, 204, 76,},{0}, OFN_SHOWHELP}, /* bug #17748*/
/* tests with size of the stc32 control higher or wider then the standard dialog */
{ 1, {0, 0, 316, 170} ,{0, 0, 204, 170,},{0},0 },
{ 1, {0, 0, 316, 165} ,{0, 0, 411, 165,},{0}, OFN_SHOWHELP },
/* move the stc32 control around */
{ 1, {0, 0, 300, 100} ,{73, 17, 50, 50,},{0},0 },
/* add control */
{ 2, {0, 0, 280, 100} ,{0, 0, 50, 50,},{300,20,30,30},0 },
/* enable resizing should make the dialog bigger */
{ 0, {0},{0},{0}, OFN_SHOWHELP|OFN_ENABLESIZING},
/* mark the end */
{ -1 }
};
static LONG_PTR WINAPI template_hook_arrange(HWND dlgChild, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int index, fixhelp;
static posz posz0[2];
static RECT clrcParent, clrcChild, rcStc32;
static HWND hwndStc32;
HWND dlgParent;
dlgParent = GetParent( dlgChild);
if (msg == WM_INITDIALOG) {
index = ((OPENFILENAME*)lParam)->lCustData;
/* get the positions before rearrangement */
GetClientRect( dlgParent, &clrcParent);
GetClientRect( dlgChild, &clrcChild);
hwndStc32 = GetDlgItem( dlgChild, stc32);
if( hwndStc32) GetWindowRect( hwndStc32, &rcStc32);
}
if (msg == WM_NOTIFY && ((LPNMHDR)lParam)->code == CDN_FOLDERCHANGE) {
RECT wrcParent;
GetWindowRect( dlgParent, &wrcParent);
/* the fist two "tests" just save the dialogs position, with and without
* help button */
if( index == 0) {
posz0[0].x = wrcParent.left;
posz0[0].y = wrcParent.top;
posz0[0].cx = wrcParent.right - wrcParent.left;
posz0[0].cy = wrcParent.bottom - wrcParent.top;
} else if( index == 1) {
posz0[1].x = wrcParent.left;
posz0[1].y = wrcParent.top;
posz0[1].cx = wrcParent.right - wrcParent.left;
posz0[1].cy = wrcParent.bottom - wrcParent.top;
fixhelp = posz0[1].cy - posz0[0].cy;
} else {
/* the real tests */
int withhelp;
int expectx, expecty;
withhelp = (arrange_tests[index].ofnflags & OFN_SHOWHELP) != 0;
GetWindowRect( dlgParent, &wrcParent);
if( !hwndStc32) {
/* case with no custom subitem with stc32:
* default to all custom controls below the standard */
expecty = posz0[withhelp].cy + clrcChild.bottom;
expectx = posz0[withhelp].cx;
} else {
/* special case: there is a control with id stc32 */
/* expected height */
expecty = posz0[withhelp].cy;
if( rcStc32.bottom - rcStc32.top > clrcParent.bottom) {
expecty += clrcChild.bottom - clrcParent.bottom;
if( !withhelp) expecty += fixhelp;
}
else
expecty += clrcChild.bottom - ( rcStc32.bottom - rcStc32.top) ;
/* expected width */
expectx = posz0[withhelp].cx;
if( rcStc32.right - rcStc32.left > clrcParent.right) {
expectx += clrcChild.right - clrcParent.right;
}
else
expectx += clrcChild.right - ( rcStc32.right - rcStc32.left) ;
}
if( !(arrange_tests[index].ofnflags & OFN_ENABLESIZING)) {
ok( wrcParent.bottom - wrcParent.top == expecty,
"Wrong height of dialog %d, expected %d\n",
wrcParent.bottom - wrcParent.top, expecty);
ok( wrcParent.right - wrcParent.left == expectx,
"Wrong width of dialog %d, expected %d\n",
wrcParent.right - wrcParent.left, expectx);
} else todo_wine {
ok( wrcParent.bottom - wrcParent.top > expecty,
"Wrong height of dialog %d, expected more than %d\n",
wrcParent.bottom - wrcParent.top, expecty);
ok( wrcParent.right - wrcParent.left > expectx,
"Wrong width of dialog %d, expected more than %d\n",
wrcParent.right - wrcParent.left, expectx);
}
}
PostMessage( dlgParent, WM_COMMAND, IDCANCEL, 0);
}
return 0;
}
static void test_arrange(void)
{
OPENFILENAMEA ofn = {0};
char filename[1024] = {0};
DWORD ret;
HRSRC hRes;
HANDLE hDlgTmpl;
LPBYTE pv;
DLGTEMPLATE *template;
DLGITEMTEMPLATE *itemtemplateStc32, *itemtemplateBtn;
int i;
/* load subdialog template into memory */
hRes = FindResource( GetModuleHandle(NULL), "template_stc32", (LPSTR)RT_DIALOG);
hDlgTmpl = LoadResource( GetModuleHandle(NULL), hRes );
/* get pointers to the structures for the dialog and the controls */
pv = LockResource( hDlgTmpl );
template = (DLGTEMPLATE*)pv;
if( template->x != 11111) {
win_skip("could not find the dialog template\n");
return;
}
/* skip dialog template, menu, class and title */
pv += sizeof(DLGTEMPLATE);
pv += 3 * sizeof(WORD);
/* skip font info */
while( *(WORD*)pv)
pv += sizeof(WORD);
pv += sizeof(WORD);
/* align on 32 bit boundaries */
pv = (LPBYTE)(((UINT_PTR)pv + 3 ) & ~3);
itemtemplateStc32 = (DLGITEMTEMPLATE*)pv;
if( itemtemplateStc32->x != 22222) {
win_skip("could not find the first item template\n");
return;
}
/* skip itemtemplate, class, title and creation data */
pv += sizeof(DLGITEMTEMPLATE);
pv += 4 * sizeof(WORD);
/* align on 32 bit boundaries */
pv = (LPBYTE)(((UINT_PTR)pv + 3 ) & ~3);
itemtemplateBtn = (DLGITEMTEMPLATE*)pv;
if( itemtemplateBtn->x != 12345) {
win_skip("could not find the second item template\n");
return;
}
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = filename;
ofn.nMaxFile = 1024;
ofn.lpfnHook = (LPOFNHOOKPROC)template_hook_arrange;
ofn.hInstance = hDlgTmpl;
ofn.lpstrFilter="text\0*.txt\0All\0*\0\0";
for( i = 0; arrange_tests[i].nrcontrols != -1; i++) {
ofn.lCustData = i;
ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER| OFN_ENABLETEMPLATEHANDLE | OFN_HIDEREADONLY |
arrange_tests[i].ofnflags;
template->cdit = arrange_tests[i].nrcontrols;
template->x = arrange_tests[i].poszDlg.x;
template->y = arrange_tests[i].poszDlg.y;
template->cx = arrange_tests[i].poszDlg.cx;
template->cy = arrange_tests[i].poszDlg.cy;
itemtemplateStc32->x = arrange_tests[i].poszStc32.x;
itemtemplateStc32->y = arrange_tests[i].poszStc32.y;
itemtemplateStc32->cx = arrange_tests[i].poszStc32.cx;
itemtemplateStc32->cy = arrange_tests[i].poszStc32.cy;
itemtemplateBtn->x = arrange_tests[i].poszBtn.x;
itemtemplateBtn->y = arrange_tests[i].poszBtn.y;
itemtemplateBtn->cx = arrange_tests[i].poszBtn.cx;
itemtemplateBtn->cy = arrange_tests[i].poszBtn.cy;
ret = GetOpenFileNameA(&ofn);
ok(!ret, "GetOpenFileNameA returned %#x\n", ret);
ret = CommDlgExtendedError();
ok(!ret, "CommDlgExtendedError returned %#x\n", ret);
}
}
START_TEST(filedlg)
{
test_DialogCancel();
test_create_view_window2();
test_create_view_template();
test_arrange();
test_resize();
test_ok();
}
......@@ -48,3 +48,12 @@ FONT 8, "MS Shell Dlg"
LTEXT "",-1,28,16,204,31
EDITTEXT 56,65,2,200,12,ES_AUTOHSCROLL
}
/* note: the test program will modify coordinates and nr of controls in this template */
TEMPLATE_STC32 DIALOG LOADONCALL MOVEABLE DISCARDABLE 11111, 0, 316, 76
STYLE WS_CHILD | WS_CLIPSIBLINGS
FONT 8, "MS Shell Dlg"
{
LTEXT "", 1119, 22222, 0, 204, 76
PUSHBUTTON "TEST", -1, 12345, 0, 20, 20
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment