📄 dialog.c
字号:
infoPtr->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
if (!IsWindow( infoPtr->hwndFocus )) return;
}
SetFocus( infoPtr->hwndFocus );
/* This used to set infoPtr->hwndFocus to NULL for no apparent reason,
sometimes losing focus when receiving WM_SETFOCUS messages. */
}
/***********************************************************************
* DEFDLG_FindDefButton
*
* Find the current default push-button.
*/
static HWND DEFDLG_FindDefButton( HWND hwndDlg )
{
HWND hwndChild, hwndTmp;
hwndChild = GetWindow( hwndDlg, GW_CHILD );
while (hwndChild)
{
if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
break;
/* Recurse into WS_EX_CONTROLPARENT controls */
if (GetWindowLongW( hwndChild, GWL_EXSTYLE ) & WS_EX_CONTROLPARENT)
{
LONG dsStyle = GetWindowLongW( hwndChild, GWL_STYLE );
if ((dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED) &&
(hwndTmp = DEFDLG_FindDefButton(hwndChild)) != NULL)
return hwndTmp;
}
hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
}
return hwndChild;
}
/***********************************************************************
* DEFDLG_SetDefId
*
* Set the default button id.
*/
static BOOL DEFDLG_SetDefId( HWND hwndDlg, DIALOGINFO *dlgInfo, WPARAM wParam)
{
DWORD dlgcode=0; /* initialize just to avoid a warning */
HWND hwndOld, hwndNew = GetDlgItem(hwndDlg, wParam);
INT old_id = dlgInfo->idResult;
dlgInfo->idResult = wParam;
if (hwndNew &&
!((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
& (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
return FALSE; /* Destination is not a push button */
/* Make sure the old default control is a valid push button ID */
hwndOld = GetDlgItem( hwndDlg, old_id );
if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
hwndOld = DEFDLG_FindDefButton( hwndDlg );
if (hwndOld && hwndOld != hwndNew)
SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
if (hwndNew)
{
if(dlgcode & DLGC_UNDEFPUSHBUTTON)
SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
}
return TRUE;
}
/***********************************************************************
* DEFDLG_SetDefButton
*
* Set the new default button to be hwndNew.
*/
static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, HWND hwndNew )
{
DWORD dlgcode=0; /* initialize just to avoid a warning */
HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
if (hwndNew &&
!((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
& (DLGC_UNDEFPUSHBUTTON | DLGC_DEFPUSHBUTTON)))
{
/**
* Need to draw only default push button rectangle.
* Since the next control is not a push button, need to draw the push
* button rectangle for the default control.
*/
hwndNew = hwndOld;
dlgcode = SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 );
}
/* Make sure the old default control is a valid push button ID */
if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
hwndOld = DEFDLG_FindDefButton( hwndDlg );
if (hwndOld && hwndOld != hwndNew)
SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
if (hwndNew)
{
if(dlgcode & DLGC_UNDEFPUSHBUTTON)
SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
}
return TRUE;
}
/***********************************************************************
* DEFDLG_Proc
*
* Implementation of DefDlgProc(). Only handle messages that need special
* handling for dialogs.
*/
static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam, DIALOGINFO *dlgInfo )
{
switch(msg)
{
case WM_ERASEBKGND:
{
HBRUSH brush = (HBRUSH)SendMessageW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
if (!brush) brush = (HBRUSH)DefWindowProcW( hwnd, WM_CTLCOLORDLG, wParam, (LPARAM)hwnd );
if (brush)
{
RECT rect;
HDC hdc = (HDC)wParam;
GetClientRect( hwnd, &rect );
DPtoLP( hdc, (LPPOINT)&rect, 2 );
FillRect( hdc, &rect, brush );
}
return 1;
}
case WM_NCDESTROY:
if ((dlgInfo = (DIALOGINFO *)SetWindowLongPtrW( hwnd, DWLP_ROS_DIALOGINFO, 0 )))
{
/* Free dialog heap (if created) */
/*if (dlgInfo->hDialogHeap)
{
GlobalUnlock16(dlgInfo->hDialogHeap);
GlobalFree16(dlgInfo->hDialogHeap);
}*/
if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
HeapFree( GetProcessHeap(), 0, dlgInfo );
}
/* Window clean-up */
return DefWindowProcA( hwnd, msg, wParam, lParam );
case WM_SHOWWINDOW:
if (!wParam) DEFDLG_SaveFocus( hwnd );
return DefWindowProcA( hwnd, msg, wParam, lParam );
case WM_ACTIVATE:
if (wParam) DEFDLG_RestoreFocus( hwnd );
else DEFDLG_SaveFocus( hwnd );
return 0;
case WM_SETFOCUS:
DEFDLG_RestoreFocus( hwnd );
return 0;
case DM_SETDEFID:
if (dlgInfo && !(dlgInfo->flags & DF_END))
DEFDLG_SetDefId( hwnd, dlgInfo, wParam );
return 1;
case DM_GETDEFID:
if (dlgInfo && !(dlgInfo->flags & DF_END))
{
HWND hwndDefId;
if (dlgInfo->idResult)
return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
}
return 0;
case WM_NEXTDLGCTL:
if (dlgInfo)
{
HWND hwndDest = (HWND)wParam;
if (!lParam)
hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
if (hwndDest) DEFDLG_SetFocus( hwnd, hwndDest );
DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
}
return 0;
case WM_ENTERMENULOOP:
case WM_LBUTTONDOWN:
case WM_NCLBUTTONDOWN:
{
HWND hwndFocus = GetFocus();
if (hwndFocus)
{
/* always make combo box hide its listbox control */
if (!SendMessageW( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
SendMessageW( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
}
}
return DefWindowProcA( hwnd, msg, wParam, lParam );
case WM_GETFONT:
return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0;
case WM_CLOSE:
PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED),
(LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
return 0;
}
return 0;
}
/***********************************************************************
* DEFDLG_Epilog
*/
static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, BOOL fResult)
{
// TODO: where's wine's WM_CTLCOLOR from?
if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
msg == WM_CTLCOLOR || msg == WM_COMPAREITEM ||
msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
return fResult;
return GetWindowLongPtrW( hwnd, DWLP_MSGRESULT );
}
/***********************************************************************
* DIALOG_GetNextTabItem
*
* Helper for GetNextDlgTabItem
*/
static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
{
LONG dsStyle;
LONG exStyle;
UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT;
HWND retWnd = 0;
HWND hChildFirst = 0;
if(!hwndCtrl)
{
hChildFirst = GetWindow(hwndDlg,GW_CHILD);
if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST);
}
else if (IsChild( hwndMain, hwndCtrl ))
{
hChildFirst = GetWindow(hwndCtrl,wndSearch);
if(!hChildFirst)
{
if(GetParent(hwndCtrl) != hwndMain)
/* i.e. if we are not at the top level of the recursion */
hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch);
else
hChildFirst = GetWindow(hwndCtrl, fPrevious ? GW_HWNDLAST : GW_HWNDFIRST);
}
}
while(hChildFirst)
{
dsStyle = GetWindowLongA(hChildFirst,GWL_STYLE);
exStyle = GetWindowLongA(hChildFirst,GWL_EXSTYLE);
if( (exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
{
HWND retWnd;
retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
if (retWnd) return (retWnd);
}
else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
{
return (hChildFirst);
}
hChildFirst = GetWindow(hChildFirst,wndSearch);
}
if(hwndCtrl)
{
HWND hParent = GetParent(hwndCtrl);
while(hParent)
{
if(hParent == hwndMain) break;
retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious );
if(retWnd) break;
hParent = GetParent(hParent);
}
if(!retWnd)
retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious );
}
return retWnd ? retWnd : hwndCtrl;
}
/**********************************************************************
* DIALOG_DlgDirListW
*
* Helper function for DlgDirList*W
*/
static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
INT idStatic, UINT attrib, BOOL combo )
{
HWND hwnd;
LPWSTR orig_spec = spec;
WCHAR any[] = {'*','.','*',0};
#define SENDMSG(msg,wparam,lparam) \
((attrib & DDL_POSTMSGS) ? PostMessageW( hwnd, msg, wparam, lparam ) \
: SendMessageW( hwnd, msg, wparam, lparam ))
// DPRINT("%p '%s' %d %d %04x\n",
// hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib );
/* If the path exists and is a directory, chdir to it */
if (!spec || !spec[0] || SetCurrentDirectoryW( spec )) spec = any;
else
{
WCHAR *p, *p2;
p = spec;
if ((p2 = strrchrW( p, '\\' ))) p = p2;
if ((p2 = strrchrW( p, '/' ))) p = p2;
if (p != spec)
{
WCHAR sep = *p;
*p = 0;
if (!SetCurrentDirectoryW( spec ))
{
*p = sep; /* Restore the original spec */
return FALSE;
}
spec = p + 1;
}
}
DPRINT( "mask=%s\n", spec );
if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
{
SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 );
if (attrib & DDL_DIRECTORY)
{
if (!(attrib & DDL_EXCLUSIVE))
{
if (SENDMSG( combo ? CB_DIR : LB_DIR,
attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
(LPARAM)spec ) == LB_ERR)
return FALSE;
}
if (SENDMSG( combo ? CB_DIR : LB_DIR,
(attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
(LPARAM)any ) == LB_ERR)
return FALSE;
}
else
{
if (SENDMSG( combo ? CB_DIR : LB_DIR, attrib,
(LPARAM)spec ) == LB_ERR)
return FALSE;
}
}
if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
{
WCHAR temp[MAX_PATH];
GetCurrentDirectoryW( sizeof(temp)/sizeof(WCHAR), temp );
CharLowerW( temp );
/* Can't use PostMessage() here, because the string is on the stack */
SetDlgItemTextW( hDlg, idStatic, temp );
}
if (orig_spec && (spec != orig_spec))
{
/* Update the original file spec */
WCHAR *p = spec;
while ((*orig_spec++ = *p++));
}
return TRUE;
#undef SENDMSG
}
/**********************************************************************
* DIALOG_DlgDirListA
*
* Helper function for DlgDirList*A
*/
static INT DIALOG_DlgDirListA( HWND hDlg, LPSTR spec, INT idLBox,
INT idStatic, UINT attrib, BOOL combo )
{
if (spec)
{
INT ret, len = MultiByteToWideChar( CP_ACP, 0, spec, -1, NULL, 0 );
LPWSTR specW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, spec, -1, specW, len );
ret = DIALOG_DlgDirListW( hDlg, specW, idLBox, idStatic, attrib, combo );
WideCharToMultiByte( CP_ACP, 0, specW, -1, spec, 0x7fffffff, NULL, NULL );
HeapFree( GetProcessHeap(), 0, specW );
return ret;
}
return DIALOG_DlgDirListW( hDlg, NULL, idLBox, idStatic, attrib, combo );
}
/**********************************************************************
* DIALOG_DlgDirSelect
*
* Helper function for DlgDirSelect*
*/
static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPWSTR str, INT len,
INT id, BOOL unicode, BOOL combo )
{
WCHAR *buffer, *ptr;
INT item, size;
BOOL ret;
HWND listbox = GetDlgItem( hwnd, id );
DPRINT("%p '%s' %d\n", hwnd, str, id );
if (!listbox) return FALSE;
item = SendMessageW(listbox, combo ? CB_GETCURSEL : LB_GETCURSEL, 0, 0 );
if (item == LB_ERR) return FALSE;
size = SendMessageW(listbox, combo ? CB_GETLBTEXTLEN : LB_GETTEXTLEN, 0, 0 );
if (size == LB_ERR) return FALSE;
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size+1 ))) return FALSE;
SendMessageW( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT, item, (LPARAM)buffer );
if ((ret = (buffer[0] == '['))) /* drive or directory */
{
if (buffer[1] == '-') /* drive */
{
buffer[3] = ':';
buffer[4] = 0;
ptr = buffer + 2;
}
else
{
buffer[strlenW(buffer)-1] = '\\';
ptr = buffer + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -