📄 dialog.c
字号:
static const WCHAR query[] = {
's','e','l','e','c','t',' ','*',' ',
'f','r','o','m',' ','B','i','n','a','r','y',' ',
'w','h','e','r','e',' ',
'`','N','a','m','e','`',' ','=',' ','\'','%','s','\'',0
};
return MSI_QueryGetRecord( db, query, name );
}
static LPWSTR msi_create_tmp_path(void)
{
WCHAR tmp[MAX_PATH];
LPWSTR path = NULL;
static const WCHAR prefix[] = { 'm','s','i',0 };
DWORD len, r;
r = GetTempPathW( MAX_PATH, tmp );
if( !r )
return path;
len = lstrlenW( tmp ) + 20;
path = msi_alloc( len * sizeof (WCHAR) );
if( path )
{
r = GetTempFileNameW( tmp, prefix, 0, path );
if (!r)
{
msi_free( path );
path = NULL;
}
}
return path;
}
static HANDLE msi_load_image( MSIDATABASE *db, LPCWSTR name, UINT type,
UINT cx, UINT cy, UINT flags )
{
MSIRECORD *rec = NULL;
HANDLE himage = NULL;
LPWSTR tmp;
UINT r;
TRACE("%p %s %u %u %08x\n", db, debugstr_w(name), cx, cy, flags);
tmp = msi_create_tmp_path();
if( !tmp )
return himage;
rec = msi_get_binary_record( db, name );
if( rec )
{
r = MSI_RecordStreamToFile( rec, 2, tmp );
if( r == ERROR_SUCCESS )
{
himage = LoadImageW( 0, tmp, type, cx, cy, flags );
DeleteFileW( tmp );
}
msiobj_release( &rec->hdr );
}
msi_free( tmp );
return himage;
}
static HICON msi_load_icon( MSIDATABASE *db, LPCWSTR text, UINT attributes )
{
DWORD cx = 0, cy = 0, flags;
flags = LR_LOADFROMFILE | LR_DEFAULTSIZE;
if( attributes & msidbControlAttributesFixedSize )
{
flags &= ~LR_DEFAULTSIZE;
if( attributes & msidbControlAttributesIconSize16 )
{
cx += 16;
cy += 16;
}
if( attributes & msidbControlAttributesIconSize32 )
{
cx += 32;
cy += 32;
}
/* msidbControlAttributesIconSize48 handled by above logic */
}
return msi_load_image( db, text, IMAGE_ICON, cx, cy, flags );
}
/* called from the Control Event subscription code */
void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
LPCWSTR attribute, MSIRECORD *rec )
{
msi_control* ctrl;
LPCWSTR font_text, text = NULL;
LPWSTR font;
static const WCHAR empty[] = {0};
ctrl = msi_dialog_find_control( dialog, control );
if (!ctrl)
return;
if( !lstrcmpW(attribute, szText) )
{
font_text = MSI_RecordGetString( rec , 1 );
font = msi_dialog_get_style( font_text, &text );
if (!text) text = empty;
SetWindowTextW( ctrl->hwnd, text );
msi_free( font );
msi_dialog_check_messages( NULL );
}
else if( !lstrcmpW(attribute, szProgress) )
{
DWORD func, val;
func = MSI_RecordGetInteger( rec , 1 );
val = MSI_RecordGetInteger( rec , 2 );
switch (func)
{
case 0: /* init */
ctrl->progress_max = val;
ctrl->progress_current = 0;
SendMessageW(ctrl->hwnd, PBM_SETRANGE, 0, MAKELPARAM(0,100));
SendMessageW(ctrl->hwnd, PBM_SETPOS, 0, 0);
break;
case 1: /* FIXME: not sure what this is supposed to do */
break;
case 2: /* move */
ctrl->progress_current += val;
SendMessageW(ctrl->hwnd, PBM_SETPOS, 100*(ctrl->progress_current/ctrl->progress_max), 0);
break;
default:
ERR("Unknown progress message %d\n", func);
break;
}
}
else if ( !lstrcmpW(attribute, szProperty) )
{
MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
MSI_SetPropertyW( dialog->package, ctrl->property, feature->Directory );
}
else
{
FIXME("Attribute %s not being set\n", debugstr_w(attribute));
return;
}
}
static void msi_dialog_map_events(msi_dialog* dialog, LPCWSTR control)
{
static const WCHAR Query[] = {
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','E','v','e','n','t','M','a','p','p','i','n','g','`',' ',
'W','H','E','R','E',' ',
'`','D','i','a','l','o','g','_','`',' ','=',' ','\'','%','s','\'',' ',
'A','N','D',' ',
'`','C','o','n','t','r','o','l','_','`',' ','=',' ','\'','%','s','\'',0
};
MSIRECORD *row;
LPCWSTR event, attribute;
row = MSI_QueryGetRecord( dialog->package->db, Query, dialog->name, control );
if (!row)
return;
event = MSI_RecordGetString( row, 3 );
attribute = MSI_RecordGetString( row, 4 );
ControlEvent_SubscribeToEvent( dialog->package, dialog, event, control, attribute );
msiobj_release( &row->hdr );
}
/* everything except radio buttons */
static msi_control *msi_dialog_add_control( msi_dialog *dialog,
MSIRECORD *rec, LPCWSTR szCls, DWORD style )
{
DWORD attributes;
LPCWSTR text, name;
DWORD exstyle = 0;
name = MSI_RecordGetString( rec, 2 );
attributes = MSI_RecordGetInteger( rec, 8 );
text = MSI_RecordGetString( rec, 10 );
if( attributes & msidbControlAttributesVisible )
style |= WS_VISIBLE;
if( ~attributes & msidbControlAttributesEnabled )
style |= WS_DISABLED;
if( attributes & msidbControlAttributesSunken )
exstyle |= WS_EX_CLIENTEDGE;
msi_dialog_map_events(dialog, name);
return msi_dialog_create_window( dialog, rec, exstyle, szCls, name,
text, style, dialog->hwnd );
}
struct msi_text_info
{
msi_font *font;
WNDPROC oldproc;
DWORD attributes;
};
/*
* we don't erase our own background,
* so we have to make sure that the parent window redraws first
*/
static void msi_text_on_settext( HWND hWnd )
{
HWND hParent;
RECT rc;
hParent = GetParent( hWnd );
GetWindowRect( hWnd, &rc );
MapWindowPoints( NULL, hParent, (LPPOINT) &rc, 2 );
InvalidateRect( hParent, &rc, TRUE );
}
static LRESULT WINAPI
MSIText_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
struct msi_text_info *info;
LRESULT r = 0;
TRACE("%p %04x %08x %08lx\n", hWnd, msg, wParam, lParam);
info = GetPropW(hWnd, szButtonData);
if ( info->font )
SetTextColor( (HDC)wParam, info->font->color );
if( msg == WM_CTLCOLORSTATIC &&
( info->attributes & msidbControlAttributesTransparent ) )
{
SetBkMode( (HDC)wParam, TRANSPARENT );
return (LRESULT) GetStockObject(NULL_BRUSH);
}
r = CallWindowProcW(info->oldproc, hWnd, msg, wParam, lParam);
switch( msg )
{
case WM_SETTEXT:
msi_text_on_settext( hWnd );
break;
case WM_NCDESTROY:
msi_free( info );
RemovePropW( hWnd, szButtonData );
break;
}
return r;
}
static UINT msi_dialog_text_control( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
struct msi_text_info *info;
LPCWSTR text, ptr;
LPWSTR font_name;
TRACE("%p %p\n", dialog, rec);
control = msi_dialog_add_control( dialog, rec, szStatic, SS_LEFT | WS_GROUP );
if( !control )
return ERROR_FUNCTION_FAILED;
info = msi_alloc( sizeof *info );
if( !info )
return ERROR_SUCCESS;
text = MSI_RecordGetString( rec, 10 );
font_name = msi_dialog_get_style( text, &ptr );
info->font = ( font_name ) ? msi_dialog_find_font( dialog, font_name ) : NULL;
msi_free( font_name );
info->attributes = MSI_RecordGetInteger( rec, 8 );
if( info->attributes & msidbControlAttributesTransparent )
SetWindowLongPtrW( control->hwnd, GWL_EXSTYLE, WS_EX_TRANSPARENT );
info->oldproc = (WNDPROC) SetWindowLongPtrW( control->hwnd, GWLP_WNDPROC,
(LONG_PTR)MSIText_WndProc );
SetPropW( control->hwnd, szButtonData, info );
return ERROR_SUCCESS;
}
static UINT msi_dialog_button_control( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
UINT attributes, style;
LPWSTR text;
TRACE("%p %p\n", dialog, rec);
style = WS_TABSTOP;
attributes = MSI_RecordGetInteger( rec, 8 );
if( attributes & msidbControlAttributesIcon )
style |= BS_ICON;
control = msi_dialog_add_control( dialog, rec, szButton, style );
if( !control )
return ERROR_FUNCTION_FAILED;
control->handler = msi_dialog_button_handler;
/* set the icon */
text = msi_get_deformatted_field( dialog->package, rec, 10 );
control->hIcon = msi_load_icon( dialog->package->db, text, attributes );
if( attributes & msidbControlAttributesIcon )
SendMessageW( control->hwnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM) control->hIcon );
msi_free( text );
return ERROR_SUCCESS;
}
static LPWSTR msi_get_checkbox_value( msi_dialog *dialog, LPCWSTR prop )
{
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ',
'F','R','O','M',' ','`','C','h','e','c','k','B','o','x',' ','`',
'W','H','E','R','E',' ',
'`','P','r','o','p','e','r','t','y','`',' ','=',' ',
'\'','%','s','\'',0
};
MSIRECORD *rec = NULL;
LPWSTR ret = NULL;
/* find if there is a value associated with the checkbox */
rec = MSI_QueryGetRecord( dialog->package->db, query, prop );
if (!rec)
return ret;
ret = msi_get_deformatted_field( dialog->package, rec, 2 );
if( ret && !ret[0] )
{
msi_free( ret );
ret = NULL;
}
msiobj_release( &rec->hdr );
if (ret)
return ret;
ret = msi_dup_property( dialog->package, prop );
if( ret && !ret[0] )
{
msi_free( ret );
ret = NULL;
}
return ret;
}
static UINT msi_dialog_checkbox_control( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
LPCWSTR prop;
TRACE("%p %p\n", dialog, rec);
control = msi_dialog_add_control( dialog, rec, szButton,
BS_CHECKBOX | BS_MULTILINE | WS_TABSTOP );
control->handler = msi_dialog_checkbox_handler;
prop = MSI_RecordGetString( rec, 9 );
if( prop )
{
control->property = strdupW( prop );
control->value = msi_get_checkbox_value( dialog, prop );
TRACE("control %s value %s\n", debugstr_w(control->property),
debugstr_w(control->value));
}
msi_dialog_checkbox_sync_state( dialog, control );
return ERROR_SUCCESS;
}
static UINT msi_dialog_line_control( msi_dialog *dialog, MSIRECORD *rec )
{
TRACE("%p %p\n", dialog, rec);
/* line is exactly 2 units in height */
MSI_RecordSetInteger( rec, 7, 2 );
msi_dialog_add_control( dialog, rec, szStatic, SS_ETCHEDHORZ | SS_SUNKEN );
return ERROR_SUCCESS;
}
/******************** Scroll Text ********************************************/
struct msi_scrolltext_info
{
msi_dialog *dialog;
msi_control *control;
WNDPROC oldproc;
};
static LRESULT WINAPI
MSIScrollText_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
struct msi_scrolltext_info *info;
HRESULT r;
TRACE("%p %04x %08x %08lx\n", hWnd, msg, wParam, lParam);
info = GetPropW( hWnd, szButtonData );
r = CallWindowProcW( info->oldproc, hWnd, msg, wParam, lParam );
switch( msg )
{
case WM_NCDESTROY:
msi_free( info );
RemovePropW( hWnd, szButtonData );
break;
case WM_PAINT:
/* native MSI sets a wait cursor here */
msi_dialog_button_handler( info->dialog, info->control, BN_CLICKED );
break;
}
return r;
}
struct msi_streamin_info
{
LPSTR string;
DWORD offset;
DWORD length;
};
static DWORD CALLBACK
msi_richedit_stream_in( DWORD_PTR arg, LPBYTE buffer, LONG count, LONG *pcb )
{
struct msi_streamin_info *info = (struct msi_streamin_info*) arg;
if( (count + info->offset) > info->length )
count = info->length - info->offset;
memcpy( buffer, &info->string[ info->offset ], count );
*pcb = count;
info->offset += count;
TRACE("%d/%d\n", info->offset, info->length);
return 0;
}
static void msi_scrolltext_add_text( msi_control *control, LPCWSTR text )
{
struct msi_streamin_info info;
EDITSTREAM es;
info.string = strdupWtoA( text );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -