dialog.c
来自「一个类似windows」· C语言 代码 · 共 2,228 行 · 第 1/5 页
C
2,228 行
arg = MSI_RecordGetString( rec, 4 );
if( event[0] == '[' )
msi_dialog_set_property( dialog, event, arg );
else
msi_dialog_send_event( dialog, event, arg );
}
return ERROR_SUCCESS;
}
static UINT msi_dialog_button_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ',
'F','R','O','M',' ','C','o','n','t','r','o','l','E','v','e','n','t',' ',
'W','H','E','R','E',' ',
'`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',' ',
'A','N','D',' ',
'`','C','o','n','t','r','o','l','_','`',' ','=',' ','\'','%','s','\'',' ',
'O','R','D','E','R',' ','B','Y',' ','`','O','r','d','e','r','i','n','g','`',0
};
MSIQUERY *view = NULL;
UINT r;
if( HIWORD(param) != BN_CLICKED )
return ERROR_SUCCESS;
r = MSI_OpenQuery( dialog->package->db, &view, query,
dialog->name, control->name );
if( r != ERROR_SUCCESS )
{
ERR("query failed\n");
return 0;
}
r = MSI_IterateRecords( view, 0, msi_dialog_control_event, dialog );
msiobj_release( &view->hdr );
return r;
}
static UINT msi_dialog_get_checkbox_state( msi_dialog *dialog,
msi_control *control )
{
WCHAR state[2] = { 0 };
DWORD sz = 2;
MSI_GetPropertyW( dialog->package, control->property, state, &sz );
return state[0] ? 1 : 0;
}
static void msi_dialog_set_checkbox_state( msi_dialog *dialog,
msi_control *control, UINT state )
{
static const WCHAR szState[] = { '1', 0 };
LPCWSTR val;
/* if uncheck then the property is set to NULL */
if (!state)
{
MSI_SetPropertyW( dialog->package, control->property, NULL );
return;
}
/* check for a custom state */
if (control->value && control->value[0])
val = control->value;
else
val = szState;
MSI_SetPropertyW( dialog->package, control->property, val );
}
static void msi_dialog_checkbox_sync_state( msi_dialog *dialog,
msi_control *control )
{
UINT state;
state = msi_dialog_get_checkbox_state( dialog, control );
SendMessageW( control->hwnd, BM_SETCHECK,
state ? BST_CHECKED : BST_UNCHECKED, 0 );
}
static UINT msi_dialog_checkbox_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
UINT state;
if( HIWORD(param) != BN_CLICKED )
return ERROR_SUCCESS;
TRACE("clicked checkbox %s, set %s\n", debugstr_w(control->name),
debugstr_w(control->property));
state = msi_dialog_get_checkbox_state( dialog, control );
state = state ? 0 : 1;
msi_dialog_set_checkbox_state( dialog, control, state );
msi_dialog_checkbox_sync_state( dialog, control );
return msi_dialog_button_handler( dialog, control, param );
}
static UINT msi_dialog_edit_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
UINT sz, r;
LPWSTR buf;
if( HIWORD(param) != EN_CHANGE )
return ERROR_SUCCESS;
TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name),
debugstr_w(control->property));
sz = 0x20;
buf = msi_alloc( sz*sizeof(WCHAR) );
while( buf )
{
r = GetWindowTextW( control->hwnd, buf, sz );
if( r < (sz-1) )
break;
sz *= 2;
buf = msi_realloc( buf, sz*sizeof(WCHAR) );
}
MSI_SetPropertyW( dialog->package, control->property, buf );
msi_free( buf );
return ERROR_SUCCESS;
}
static UINT msi_dialog_radiogroup_handler( msi_dialog *dialog,
msi_control *control, WPARAM param )
{
if( HIWORD(param) != BN_CLICKED )
return ERROR_SUCCESS;
TRACE("clicked radio button %s, set %s\n", debugstr_w(control->name),
debugstr_w(control->property));
MSI_SetPropertyW( dialog->package, control->property, control->name );
return msi_dialog_button_handler( dialog, control, param );
}
static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd )
{
msi_control *control = NULL;
TRACE("%p %p %08x\n", dialog, hwnd, param);
switch (param)
{
case 1: /* enter */
control = msi_dialog_find_control( dialog, dialog->control_default );
break;
case 2: /* escape */
control = msi_dialog_find_control( dialog, dialog->control_cancel );
break;
default:
control = msi_dialog_find_control_by_hwnd( dialog, hwnd );
}
if( control )
{
if( control->handler )
{
control->handler( dialog, control, param );
msi_dialog_evaluate_control_conditions( dialog );
}
}
else
ERR("button click from nowhere %p %d %p\n", dialog, param, hwnd);
return 0;
}
static void msi_dialog_setfocus( msi_dialog *dialog )
{
HWND hwnd = dialog->hWndFocus;
hwnd = GetNextDlgTabItem( dialog->hwnd, hwnd, TRUE);
hwnd = GetNextDlgTabItem( dialog->hwnd, hwnd, FALSE);
SetFocus( hwnd );
dialog->hWndFocus = hwnd;
}
static LRESULT WINAPI MSIDialog_WndProc( HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam )
{
msi_dialog *dialog = (LPVOID) GetWindowLongPtrW( hwnd, GWLP_USERDATA );
TRACE("0x%04x\n", msg);
switch (msg)
{
case WM_CREATE:
return msi_dialog_oncreate( hwnd, (LPCREATESTRUCTW)lParam );
case WM_COMMAND:
return msi_dialog_oncommand( dialog, wParam, (HWND)lParam );
case WM_ACTIVATE:
if( LOWORD(wParam) == WA_INACTIVE )
dialog->hWndFocus = GetFocus();
else
msi_dialog_setfocus( dialog );
return 0;
case WM_SETFOCUS:
msi_dialog_setfocus( dialog );
return 0;
/* bounce back to our subclassed static control */
case WM_CTLCOLORSTATIC:
return SendMessageW( (HWND) lParam, WM_CTLCOLORSTATIC, wParam, lParam );
case WM_DESTROY:
dialog->hwnd = NULL;
return 0;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc = (WNDPROC) GetPropW(hWnd, szButtonData);
TRACE("hWnd %p msg %04x wParam 0x%08x lParam 0x%08lx\n", hWnd, msg, wParam, lParam);
if (msg == WM_COMMAND) /* Forward notifications to dialog */
SendMessageW(GetParent(hWnd), msg, wParam, lParam);
return CallWindowProcW(oldproc, hWnd, msg, wParam, lParam);
}
static LRESULT WINAPI MSIHiddenWindowProc( HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam )
{
msi_dialog *dialog = (msi_dialog*) lParam;
TRACE("%d %p\n", msg, dialog);
switch (msg)
{
case WM_MSI_DIALOG_CREATE:
return msi_dialog_run_message_loop( dialog );
case WM_MSI_DIALOG_DESTROY:
msi_dialog_destroy( dialog );
return 0;
}
return DefWindowProcW( hwnd, msg, wParam, lParam );
}
/* functions that interface to other modules within MSI */
msi_dialog *msi_dialog_create( MSIPACKAGE* package, LPCWSTR szDialogName,
msi_dialog_event_handler event_handler )
{
MSIRECORD *rec = NULL;
msi_dialog *dialog;
TRACE("%p %s\n", package, debugstr_w(szDialogName));
/* allocate the structure for the dialog to use */
dialog = msi_alloc_zero( sizeof *dialog + sizeof(WCHAR)*strlenW(szDialogName) );
if( !dialog )
return NULL;
strcpyW( dialog->name, szDialogName );
msiobj_addref( &package->hdr );
dialog->package = package;
dialog->event_handler = event_handler;
dialog->finished = 0;
list_init( &dialog->controls );
/* verify that the dialog exists */
rec = msi_get_dialog_record( dialog );
if( !rec )
{
msiobj_release( &package->hdr );
msi_free( dialog );
return NULL;
}
dialog->attributes = MSI_RecordGetInteger( rec, 6 );
dialog->control_default = strdupW( MSI_RecordGetString( rec, 9 ) );
dialog->control_cancel = strdupW( MSI_RecordGetString( rec, 10 ) );
msiobj_release( &rec->hdr );
return dialog;
}
static void msi_process_pending_messages( HWND hdlg )
{
MSG msg;
while( PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ) )
{
if( hdlg && IsDialogMessageW( hdlg, &msg ))
continue;
TranslateMessage( &msg );
DispatchMessageW( &msg );
}
}
void msi_dialog_end_dialog( msi_dialog *dialog )
{
TRACE("%p\n", dialog);
dialog->finished = 1;
PostMessageW(dialog->hwnd, WM_NULL, 0, 0);
}
void msi_dialog_check_messages( HANDLE handle )
{
DWORD r;
/* in threads other than the UI thread, block */
if( uiThreadId != GetCurrentThreadId() )
{
if( handle )
WaitForSingleObject( handle, INFINITE );
return;
}
/* there's two choices for the UI thread */
while (1)
{
msi_process_pending_messages( NULL );
if( !handle )
break;
/*
* block here until somebody creates a new dialog or
* the handle we're waiting on becomes ready
*/
r = MsgWaitForMultipleObjects( 1, &handle, 0, INFINITE, QS_ALLINPUT );
if( r == WAIT_OBJECT_0 )
break;
}
}
UINT msi_dialog_run_message_loop( msi_dialog *dialog )
{
HWND hwnd;
if( !(dialog->attributes & msidbDialogAttributesVisible) )
return ERROR_SUCCESS;
if( uiThreadId != GetCurrentThreadId() )
return SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_CREATE, 0, (LPARAM) dialog );
/* create the dialog window, don't show it yet */
hwnd = CreateWindowW( szMsiDialogClass, dialog->name, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, dialog );
if( !hwnd )
{
ERR("Failed to create dialog %s\n", debugstr_w( dialog->name ));
return ERROR_FUNCTION_FAILED;
}
ShowWindow( hwnd, SW_SHOW );
/* UpdateWindow( hwnd ); - and causes the transparent static controls not to paint */
if( dialog->attributes & msidbDialogAttributesModal )
{
while( !dialog->finished )
{
MsgWaitForMultipleObjects( 0, NULL, 0, INFINITE, QS_ALLEVENTS );
msi_process_pending_messages( dialog->hwnd );
}
}
else
return ERROR_IO_PENDING;
return ERROR_SUCCESS;
}
void msi_dialog_do_preview( msi_dialog *dialog )
{
TRACE("\n");
dialog->attributes |= msidbDialogAttributesVisible;
dialog->attributes &= ~msidbDialogAttributesModal;
msi_dialog_run_message_loop( dialog );
}
void msi_dialog_destroy( msi_dialog *dialog )
{
if( uiThreadId != GetCurrentThreadId() )
{
SendMessageW( hMsiHiddenWindow, WM_MSI_DIALOG_DESTROY, 0, (LPARAM) dialog );
return;
}
if( dialog->hwnd )
ShowWindow( dialog->hwnd, SW_HIDE );
if( dialog->hwnd )
DestroyWindow( dialog->hwnd );
/* destroy the list of controls */
while( !list_empty( &dialog->controls ) )
{
msi_control *t = LIST_ENTRY( list_head( &dialog->controls ),
msi_control, entry );
list_remove( &t->entry );
/* leave dialog->hwnd - destroying parent destroys child windows */
msi_free( t->property );
msi_free( t->value );
if( t->hBitmap )
DeleteObject( t->hBitmap );
if( t->hIcon )
DestroyIcon( t->hIcon );
msi_free( t->tabnext );
msi_free( t );
}
/* destroy the list of fonts */
while( dialog->font_list )
{
msi_font *t = dialog->font_list;
dialog->font_list = t->next;
DeleteObject( t->hfont );
msi_free( t );
}
msi_free( dialog->default_font );
msi_free( dialog->control_default );
msi_free( dialog->control_cancel );
msiobj_release( &dialog->package->hdr );
dialog->package = NULL;
msi_free( dialog );
}
BOOL msi_dialog_register_class( void )
{
WNDCLASSW cls;
ZeroMemory( &cls, sizeof cls );
cls.lpfnWndProc = MSIDialog_WndProc;
cls.hInstance = NULL;
cls.hIcon = LoadIconW(0, (LPWSTR)IDI_APPLICATION);
cls.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARRO
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?