📄 dialog.c
字号:
}
}
hwndNext = GetWindow( hwndControl, GW_CHILD );
}
else hwndNext = 0;
if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
while (!hwndNext && hwndControl)
{
hwndControl = GetParent( hwndControl );
if (hwndControl == hwndDlg)
{
if(hwnd==hwndDlg) /* prevent endless loop */
{
hwndNext=hwnd;
break;
}
hwndNext = GetWindow( hwndDlg, GW_CHILD );
}
else
hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
}
hwndControl = hwndNext;
}
while (hwndControl && (hwndControl != hwnd));
return FALSE;
}
/***********************************************************************
* DIALOG_DoDialogBox
*/
INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
{
DIALOGINFO * dlgInfo;
MSG msg;
INT retval;
HWND ownerMsg = GetAncestor( owner, GA_ROOT );
BOOL bFirstEmpty;
if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
bFirstEmpty = TRUE;
if (!(dlgInfo->flags & DF_END)) /* was EndDialog called in WM_INITDIALOG ? */
{
for (;;)
{
if (!PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
{
if (bFirstEmpty)
{
/* ShowWindow the first time the queue goes empty */
ShowWindow( hwnd, SW_SHOWNORMAL );
bFirstEmpty = FALSE;
}
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
{
/* No message present -> send ENTERIDLE and wait */
SendMessageW( ownerMsg, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd );
}
if (!GetMessageW( &msg, 0, 0, 0 )) break;
}
if (!IsWindow( hwnd )) return -1;
if (!(dlgInfo->flags & DF_END) && !IsDialogMessageW( hwnd, &msg))
{
TranslateMessage( &msg );
DispatchMessageW( &msg );
}
if (dlgInfo->flags & DF_END) break;
}
}
if (dlgInfo->flags & DF_OWNERENABLED) DIALOG_EnableOwner( owner );
retval = dlgInfo->idResult;
DestroyWindow( hwnd );
return retval;
}
/***********************************************************************
* DIALOG_ParseTemplate32
*
* Fill a DLG_TEMPLATE structure from the dialog template, and return
* a pointer to the first control.
*/
static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
{
const WORD *p = (const WORD *)template;
WORD signature;
WORD dlgver;
signature = GET_WORD(p); p++;
dlgver = GET_WORD(p); p++;
if (signature == 1 && dlgver == 0xffff) /* DIALOGEX resource */
{
result->dialogEx = TRUE;
result->helpId = GET_DWORD(p); p += 2;
result->exStyle = GET_DWORD(p); p += 2;
result->style = GET_DWORD(p); p += 2;
}
else
{
result->style = GET_DWORD(p - 2);
result->dialogEx = FALSE;
result->helpId = 0;
result->exStyle = GET_DWORD(p); p += 2;
}
result->nbItems = GET_WORD(p); p++;
result->x = GET_WORD(p); p++;
result->y = GET_WORD(p); p++;
result->cx = GET_WORD(p); p++;
result->cy = GET_WORD(p); p++;
/* Get the menu name */
switch(GET_WORD(p))
{
case 0x0000:
result->menuName = NULL;
p++;
break;
case 0xffff:
result->menuName = (LPCWSTR)(UINT)GET_WORD( p + 1 );
p += 2;
break;
default:
result->menuName = (LPCWSTR)p;
p += wcslen( result->menuName ) + 1;
break;
}
/* Get the class name */
switch(GET_WORD(p))
{
case 0x0000:
result->className = DIALOG_CLASS_ATOMW;
p++;
break;
case 0xffff:
result->className = (LPCWSTR)(UINT)GET_WORD( p + 1 );
p += 2;
break;
default:
result->className = (LPCWSTR)p;
p += wcslen( result->className ) + 1;
break;
}
/* Get the window caption */
result->caption = (LPCWSTR)p;
p += wcslen( result->caption ) + 1;
/* Get the font name */
result->pointSize = 0;
result->weight = FW_DONTCARE;
result->italic = FALSE;
result->faceName = NULL;
if (result->style & DS_SETFONT)
{
result->pointSize = GET_WORD(p);
p++;
if (result->dialogEx)
{
result->weight = GET_WORD(p); p++;
result->italic = LOBYTE(GET_WORD(p)); p++;
}
result->faceName = (LPCWSTR)p;
p += wcslen( result->faceName ) + 1;
}
/* First control is on dword boundary */
return (LPCSTR)((((int)p) + 3) & ~3);
}
/***********************************************************************
* DIALOG_CreateIndirect
* Creates a dialog box window
*
* modal = TRUE if we are called from a modal dialog box.
* (it's more compatible to do it here, as under Windows the owner
* is never disabled if the dialog fails because of an invalid template)
*/
static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
HWND owner, DLGPROC dlgProc, LPARAM param,
BOOL unicode, BOOL modal )
{
HWND hwnd;
RECT rect;
DLG_TEMPLATE template;
DIALOGINFO * dlgInfo = NULL;
DWORD units = GetDialogBaseUnits();
BOOL ownerEnabled = TRUE;
HMENU hMenu = 0;
HFONT hUserFont = 0;
UINT flags = 0;
UINT xBaseUnit = LOWORD(units);
UINT yBaseUnit = HIWORD(units);
/* Parse dialog template */
if (!dlgTemplate) return 0;
dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
/* Load menu */
if (template.menuName) hMenu = LoadMenuW( hInst, template.menuName );
/* Create custom font if needed */
if (template.style & DS_SETFONT)
{
/* We convert the size to pixels and then make it -ve. This works
* for both +ve and -ve template.pointSize */
HDC dc;
int pixels;
dc = GetDC(0);
pixels = MulDiv(template.pointSize, GetDeviceCaps(dc , LOGPIXELSY), 72);
hUserFont = CreateFontW( -pixels, 0, 0, 0, template.weight,
template.italic, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
PROOF_QUALITY, FF_DONTCARE,
template.faceName );
if (hUserFont)
{
SIZE charSize;
HFONT hOldFont = SelectObject( dc, hUserFont );
charSize.cx = GdiGetCharDimensions( dc, NULL, &charSize.cy );
if (charSize.cx)
{
xBaseUnit = charSize.cx;
yBaseUnit = charSize.cy;
}
SelectObject( dc, hOldFont );
}
ReleaseDC(0, dc);
TRACE("units = %d,%d\n", xBaseUnit, yBaseUnit );
}
/* Create dialog main window */
rect.left = rect.top = 0;
rect.right = MulDiv(template.cx, xBaseUnit, 4);
rect.bottom = MulDiv(template.cy, yBaseUnit, 8);
if (template.style & WS_CHILD)
template.style &= ~(WS_CAPTION|WS_SYSMENU);
if (template.style & DS_MODALFRAME)
template.exStyle |= WS_EX_DLGMODALFRAME;
if (template.style & DS_CONTROL)
template.exStyle |= WS_EX_CONTROLPARENT;
AdjustWindowRectEx( &rect, template.style, (hMenu != 0), template.exStyle );
rect.right -= rect.left;
rect.bottom -= rect.top;
if (template.x == CW_USEDEFAULT16)
{
rect.left = rect.top = CW_USEDEFAULT;
}
else
{
if (template.style & DS_CENTER)
{
rect.left = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
rect.top = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
}
else
{
rect.left += MulDiv(template.x, xBaseUnit, 4);
rect.top += MulDiv(template.y, yBaseUnit, 8);
}
if ( !(template.style & WS_CHILD) )
{
INT dX, dY;
if( !(template.style & DS_ABSALIGN) )
ClientToScreen( owner, (POINT *)&rect );
/* try to fit it into the desktop */
if( (dX = rect.left + rect.right + GetSystemMetrics(SM_CXDLGFRAME)
- GetSystemMetrics(SM_CXSCREEN)) > 0 ) rect.left -= dX;
if( (dY = rect.top + rect.bottom + GetSystemMetrics(SM_CYDLGFRAME)
- GetSystemMetrics(SM_CYSCREEN)) > 0 ) rect.top -= dY;
if( rect.left < 0 ) rect.left = 0;
if( rect.top < 0 ) rect.top = 0;
}
}
if (modal)
{
ownerEnabled = DIALOG_DisableOwner( owner );
if (ownerEnabled) flags |= DF_OWNERENABLED;
}
if (unicode)
{
hwnd = CreateWindowExW(template.exStyle, template.className, template.caption,
template.style & ~WS_VISIBLE,
rect.left, rect.top, rect.right, rect.bottom,
owner, hMenu, hInst, NULL );
}
else
{
LPSTR class = (LPSTR)template.className;
LPSTR caption = (LPSTR)template.caption;
if (HIWORD(class))
{
DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL );
class = HeapAlloc( GetProcessHeap(), 0, len );
WideCharToMultiByte( CP_ACP, 0, template.className, -1, class, len, NULL, NULL );
}
if (HIWORD(caption))
{
DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL );
caption = HeapAlloc( GetProcessHeap(), 0, len );
WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption, len, NULL, NULL );
}
hwnd = CreateWindowExA(template.exStyle, class, caption,
template.style & ~WS_VISIBLE,
rect.left, rect.top, rect.right, rect.bottom,
owner, hMenu, hInst, NULL );
if (HIWORD(class)) HeapFree( GetProcessHeap(), 0, class );
if (HIWORD(caption)) HeapFree( GetProcessHeap(), 0, caption );
}
if (!hwnd)
{
if (hUserFont) DeleteObject( hUserFont );
if (hMenu) DestroyMenu( hMenu );
if (modal && (flags & DF_OWNERENABLED)) DIALOG_EnableOwner(owner);
return 0;
}
/* moved this from the top of the method to here as DIALOGINFO structure
will be valid only after WM_CREATE message has been handled in DefDlgProc
All the members of the structure get filled here using temp variables */
// dlgInfo = DIALOG_get_info( hwnd, TRUE );
if (!(dlgInfo = HeapAlloc( GetProcessHeap(), 0, sizeof(*dlgInfo) ))) return 0;
SETDLGINFO(hwnd, dlgInfo);
dlgInfo->hwndFocus = 0;
dlgInfo->hUserFont = hUserFont;
dlgInfo->hMenu = hMenu;
dlgInfo->xBaseUnit = xBaseUnit;
dlgInfo->yBaseUnit = yBaseUnit;
dlgInfo->idResult = 0;
dlgInfo->flags = flags;
// dlgInfo->hDialogHeap = 0;
if (template.helpId) SetWindowContextHelpId( hwnd, template.helpId );
if (unicode) SetWindowLongPtrW( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
else SetWindowLongPtrA( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
if (dlgInfo->hUserFont)
SendMessageW( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
/* Create controls */
if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode ))
{
/* Send initialisation messages and set focus */
if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ) &&
((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE)))
{
/* By returning TRUE, app has requested a default focus assignment */
dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE);
if( dlgInfo->hwndFocus )
SetFocus( dlgInfo->hwndFocus );
}
if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
{
ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
}
return hwnd;
}
if (modal && ownerEnabled) DIALOG_EnableOwner(owner);
if( IsWindow(hwnd) ) DestroyWindow( hwnd );
return 0;
}
/***********************************************************************
* DEFDLG_SetFocus
*
* Set the focus to a control of the dialog, selecting the text if
* the control is an edit dialog.
*/
static void DEFDLG_SetFocus( HWND hwndDlg, HWND hwndCtrl )
{
HWND hwndPrev = GetFocus();
if (IsChild( hwndDlg, hwndPrev ))
{
if (SendMessageW( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
SendMessageW( hwndPrev, EM_SETSEL, -1, 0 );
}
if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
SetFocus( hwndCtrl );
}
/***********************************************************************
* DEFDLG_SaveFocus
*/
static void DEFDLG_SaveFocus( HWND hwnd )
{
DIALOGINFO *infoPtr;
HWND hwndFocus = GetFocus();
if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
if (!(infoPtr = GETDLGINFO(hwnd))) return;
infoPtr->hwndFocus = hwndFocus;
/* Remove default button */
}
/***********************************************************************
* DEFDLG_RestoreFocus
*/
static void DEFDLG_RestoreFocus( HWND hwnd )
{
DIALOGINFO *infoPtr;
if (IsIconic( hwnd )) return;
if (!(infoPtr = GETDLGINFO(hwnd))) return;
/* Don't set the focus back to controls if EndDialog is already called.*/
if (infoPtr->flags & DF_END) return;
if (!IsWindow(infoPtr->hwndFocus) || infoPtr->hwndFocus == hwnd) {
/* If no saved focus control exists, set focus to the first visible,
non-disabled, WS_TABSTOP control in the dialog */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -