dialog.c
来自「一个类似windows」· C语言 代码 · 共 2,228 行 · 第 1/5 页
C
2,228 行
}
control = msi_dialog_add_control( dialog, rec, szStatic, style );
cx = MSI_RecordGetInteger( rec, 6 );
cy = MSI_RecordGetInteger( rec, 7 );
cx = msi_dialog_scale_unit( dialog, cx );
cy = msi_dialog_scale_unit( dialog, cy );
text = msi_get_deformatted_field( dialog->package, rec, 10 );
control->hBitmap = msi_load_picture( dialog->package->db, text, cx, cy, flags );
if( control->hBitmap )
SendMessageW( control->hwnd, STM_SETIMAGE,
IMAGE_BITMAP, (LPARAM) control->hBitmap );
else
ERR("Failed to load bitmap %s\n", debugstr_w(text));
msi_free( text );
return ERROR_SUCCESS;
}
static UINT msi_dialog_icon_control( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
DWORD attributes;
LPWSTR text;
TRACE("\n");
control = msi_dialog_add_control( dialog, rec, szStatic,
SS_ICON | SS_CENTERIMAGE | WS_GROUP );
attributes = MSI_RecordGetInteger( rec, 8 );
text = msi_get_deformatted_field( dialog->package, rec, 10 );
control->hIcon = msi_load_icon( dialog->package->db, text, attributes );
if( control->hIcon )
SendMessageW( control->hwnd, STM_SETICON, (WPARAM) control->hIcon, 0 );
else
ERR("Failed to load bitmap %s\n", debugstr_w(text));
msi_free( text );
return ERROR_SUCCESS;
}
static UINT msi_dialog_combo_control( msi_dialog *dialog, MSIRECORD *rec )
{
static const WCHAR szCombo[] = { 'C','O','M','B','O','B','O','X',0 };
msi_dialog_add_control( dialog, rec, szCombo,
SS_BITMAP | SS_LEFT | SS_CENTERIMAGE );
return ERROR_SUCCESS;
}
static UINT msi_dialog_edit_control( msi_dialog *dialog, MSIRECORD *rec )
{
msi_control *control;
LPCWSTR prop;
LPWSTR val;
control = msi_dialog_add_control( dialog, rec, szEdit,
WS_BORDER | WS_TABSTOP );
control->handler = msi_dialog_edit_handler;
prop = MSI_RecordGetString( rec, 9 );
if( prop )
control->property = strdupW( prop );
val = msi_dup_property( dialog->package, control->property );
SetWindowTextW( control->hwnd, val );
msi_free( val );
return ERROR_SUCCESS;
}
/******************** Masked Edit ********************************************/
#define MASK_MAX_GROUPS 10
struct msi_mask_group
{
UINT len;
UINT ofs;
WCHAR type;
HWND hwnd;
};
struct msi_maskedit_info
{
msi_dialog *dialog;
WNDPROC oldproc;
HWND hwnd;
LPWSTR prop;
UINT num_chars;
UINT num_groups;
struct msi_mask_group group[MASK_MAX_GROUPS];
};
static BOOL msi_mask_editable( WCHAR type )
{
switch (type)
{
case '%':
case '#':
case '&':
case '`':
case '?':
case '^':
return TRUE;
}
return FALSE;
}
static void msi_mask_control_change( struct msi_maskedit_info *info )
{
LPWSTR val;
UINT i, n, r;
val = msi_alloc( (info->num_chars+1)*sizeof(WCHAR) );
for( i=0, n=0; i<info->num_groups; i++ )
{
if( (info->group[i].len + n) > info->num_chars )
{
ERR("can't fit control %d text into template\n",i);
break;
}
if (!msi_mask_editable(info->group[i].type))
{
for(r=0; r<info->group[i].len; r++)
val[n+r] = info->group[i].type;
val[n+r] = 0;
}
else
{
r = GetWindowTextW( info->group[i].hwnd, &val[n], info->group[i].len+1 );
if( r != info->group[i].len )
break;
}
n += r;
}
TRACE("%d/%d controls were good\n", i, info->num_groups);
if( i == info->num_groups )
{
TRACE("Set property %s to %s\n",
debugstr_w(info->prop), debugstr_w(val) );
CharUpperBuffW( val, info->num_chars );
MSI_SetPropertyW( info->dialog->package, info->prop, val );
msi_dialog_evaluate_control_conditions( info->dialog );
}
msi_free( val );
}
/* now move to the next control if necessary */
static VOID msi_mask_next_control( struct msi_maskedit_info *info, HWND hWnd )
{
HWND hWndNext;
UINT len, i;
for( i=0; i<info->num_groups; i++ )
if( info->group[i].hwnd == hWnd )
break;
/* don't move from the last control */
if( i >= (info->num_groups-1) )
return;
len = SendMessageW( hWnd, WM_GETTEXTLENGTH, 0, 0 );
if( len < info->group[i].len )
return;
hWndNext = GetNextDlgTabItem( GetParent( hWnd ), hWnd, FALSE );
SetFocus( hWndNext );
}
static LRESULT WINAPI
MSIMaskedEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
struct msi_maskedit_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_COMMAND:
if (HIWORD(wParam) == EN_CHANGE)
{
msi_mask_control_change( info );
msi_mask_next_control( info, (HWND) lParam );
}
break;
case WM_NCDESTROY:
msi_free( info->prop );
msi_free( info );
RemovePropW( hWnd, szButtonData );
break;
}
return r;
}
/* fish the various bits of the property out and put them in the control */
static void
msi_maskedit_set_text( struct msi_maskedit_info *info, LPCWSTR text )
{
LPCWSTR p;
UINT i;
p = text;
for( i = 0; i < info->num_groups; i++ )
{
if( info->group[i].len < lstrlenW( p ) )
{
LPWSTR chunk = strdupW( p );
chunk[ info->group[i].len ] = 0;
SetWindowTextW( info->group[i].hwnd, chunk );
msi_free( chunk );
}
else
{
SetWindowTextW( info->group[i].hwnd, p );
break;
}
p += info->group[i].len;
}
}
static struct msi_maskedit_info * msi_dialog_parse_groups( LPCWSTR mask )
{
struct msi_maskedit_info * info = NULL;
int i = 0, n = 0, total = 0;
LPCWSTR p;
TRACE("masked control, template %s\n", debugstr_w(mask));
if( !mask )
return info;
info = msi_alloc_zero( sizeof *info );
if( !info )
return info;
p = strchrW(mask, '<');
if( p )
p++;
else
p = mask;
for( i=0; i<MASK_MAX_GROUPS; i++ )
{
/* stop at the end of the string */
if( p[0] == 0 || p[0] == '>' )
break;
/* count the number of the same identifier */
for( n=0; p[n] == p[0]; n++ )
;
info->group[i].ofs = total;
info->group[i].type = p[0];
if( p[n] == '=' )
{
n++;
total++; /* an extra not part of the group */
}
info->group[i].len = n;
total += n;
p += n;
}
TRACE("%d characters in %d groups\n", total, i );
if( i == MASK_MAX_GROUPS )
ERR("too many groups in PIDTemplate %s\n", debugstr_w(mask));
info->num_chars = total;
info->num_groups = i;
return info;
}
static void
msi_maskedit_create_children( struct msi_maskedit_info *info, LPCWSTR font )
{
DWORD width, height, style, wx, ww;
RECT rect;
HWND hwnd;
UINT i;
style = WS_CHILD | WS_BORDER | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL;
GetClientRect( info->hwnd, &rect );
width = rect.right - rect.left;
height = rect.bottom - rect.top;
for( i = 0; i < info->num_groups; i++ )
{
if (!msi_mask_editable( info->group[i].type ))
continue;
wx = (info->group[i].ofs * width) / info->num_chars;
ww = (info->group[i].len * width) / info->num_chars;
hwnd = CreateWindowW( szEdit, NULL, style, wx, 0, ww, height,
info->hwnd, NULL, NULL, NULL );
if( !hwnd )
{
ERR("failed to create mask edit sub window\n");
break;
}
SendMessageW( hwnd, EM_LIMITTEXT, info->group[i].len, 0 );
msi_dialog_set_font( info->dialog, hwnd,
font?font:info->dialog->default_font );
info->group[i].hwnd = hwnd;
}
}
/*
* office 2003 uses "73931<````=````=````=````=`````>@@@@@"
* delphi 7 uses "<????-??????-??????-????>" and "<???-???>"
* filemaker pro 7 uses "<^^^^=^^^^=^^^^=^^^^=^^^^=^^^^=^^^^^>"
*/
static UINT msi_dialog_maskedit_control( msi_dialog *dialog, MSIRECORD *rec )
{
LPWSTR font_mask, val = NULL, font;
struct msi_maskedit_info *info = NULL;
UINT ret = ERROR_SUCCESS;
msi_control *control;
LPCWSTR prop, mask;
TRACE("\n");
font_mask = msi_get_deformatted_field( dialog->package, rec, 10 );
font = msi_dialog_get_style( font_mask, &mask );
if( !mask )
{
ERR("mask template is empty\n");
goto end;
}
info = msi_dialog_parse_groups( mask );
if( !info )
{
ERR("template %s is invalid\n", debugstr_w(mask));
goto end;
}
info->dialog = dialog;
control = msi_dialog_add_control( dialog, rec, szStatic,
SS_OWNERDRAW | WS_GROUP | WS_VISIBLE );
if( !control )
{
ERR("Failed to create maskedit container\n");
ret = ERROR_FUNCTION_FAILED;
goto end;
}
SetWindowLongPtrW( control->hwnd, GWL_EXSTYLE, WS_EX_CONTROLPARENT );
info->hwnd = control->hwnd;
/* subclass the static control */
info->oldproc = (WNDPROC) SetWindowLongPtrW( info->hwnd, GWLP_WNDPROC,
(LONG_PTR)MSIMaskedEdit_WndProc );
SetPropW( control->hwnd, szButtonData, info );
prop = MSI_RecordGetString( rec, 9 );
if( prop )
info->prop = strdupW( prop );
msi_maskedit_create_children( info, font );
if( prop )
{
val = msi_dup_property( dialog->package, prop );
if( val )
{
msi_maskedit_set_text( info, val );
msi_free( val );
}
}
end:
if( ret != ERROR_SUCCESS )
msi_free( info );
msi_free( font_mask );
msi_free( font );
return ret;
}
/******************** Progress Bar *****************************************/
static UINT msi_dialog_progress_bar( msi_dialog *dialog, MSIRECORD *rec )
{
msi_dialog_add_control( dialog, rec, PROGRESS_CLASSW, WS_VISIBLE );
return ERROR_SUCCESS;
}
/******************** Path Edit ********************************************/
static UINT msi_dialog_pathedit_control( msi_dialog *dialog, MSIRECORD *rec )
{
FIXME("not implemented properly\n");
return msi_dialog_edit_control( dialog, rec );
}
/* radio buttons are a bit different from normal controls */
static UINT msi_dialog_create_radiobutton( MSIRECORD *rec, LPVOID param )
{
radio_button_group_descr *group = (radio_button_group_descr *)param;
msi_dialog *dialog = group->dialog;
msi_control *control;
LPCWSTR prop, text, name;
DWORD style, attributes = group->attributes;
style = WS_CHILD | BS_AUTORADIOBUTTON | BS_MULTILINE | WS_TABSTOP;
name = MSI_RecordGetString( rec, 3 );
text = MSI_RecordGetString( rec, 8 );
if( attributes & 1 )
style |= WS_VISIBLE;
if( ~attributes & 2 )
style |= WS_DISABLED;
control = msi_dialog_create_window( dialog, rec, szButton, name, text,
style, group->parent->hwnd );
if (!control)
return ERROR_FUNCTION_FAILED;
control->handler = msi_dialog_radiogroup_handler;
prop = MSI_RecordGetString( rec, 1 );
if( prop )
control->property = strdupW( prop );
return ERROR_SUCCESS;
}
static UINT msi_dialog_radiogroup_control( msi_dialog *dialog, MSIRECORD *rec )
{
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ',
'F','R','O','M',' ','R','a','d','i','o','B','u','t','t','o','n',' ',
'W','H','E','R','E',' ',
'`','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
UINT r;
LPCWSTR prop;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?