📄 dialog.c
字号:
info.offset = 0;
info.length = lstrlenA( info.string ) + 1;
es.dwCookie = (DWORD_PTR) &info;
es.dwError = 0;
es.pfnCallback = msi_richedit_stream_in;
SendMessageW( control->hwnd, EM_STREAMIN, SF_RTF, (LPARAM) &es );
msi_free( info.string );
}
static UINT msi_dialog_scrolltext_control( msi_dialog *dialog, MSIRECORD *rec )
{
static const WCHAR szRichEdit20W[] = {
'R','i','c','h','E','d','i','t','2','0','W',0
};
struct msi_scrolltext_info *info;
msi_control *control;
HMODULE hRichedit;
LPCWSTR text;
DWORD style;
info = msi_alloc( sizeof *info );
if (!info)
return ERROR_FUNCTION_FAILED;
hRichedit = LoadLibraryA("riched20");
style = WS_BORDER | ES_MULTILINE | WS_VSCROLL |
ES_READONLY | ES_AUTOVSCROLL | WS_TABSTOP;
control = msi_dialog_add_control( dialog, rec, szRichEdit20W, style );
if (!control)
{
FreeLibrary( hRichedit );
msi_free( info );
return ERROR_FUNCTION_FAILED;
}
control->hDll = hRichedit;
info->dialog = dialog;
info->control = control;
/* subclass the static control */
info->oldproc = (WNDPROC) SetWindowLongPtrW( control->hwnd, GWLP_WNDPROC,
(LONG_PTR)MSIScrollText_WndProc );
SetPropW( control->hwnd, szButtonData, info );
/* add the text into the richedit */
text = MSI_RecordGetString( rec, 10 );
if (text)
msi_scrolltext_add_text( control, text );
return ERROR_SUCCESS;
}
static HBITMAP msi_load_picture( MSIDATABASE *db, LPCWSTR name,
INT cx, INT cy, DWORD flags )
{
HBITMAP hOleBitmap = 0, hBitmap = 0, hOldSrcBitmap, hOldDestBitmap;
MSIRECORD *rec = NULL;
IStream *stm = NULL;
IPicture *pic = NULL;
HDC srcdc, destdc;
BITMAP bm;
UINT r;
rec = msi_get_binary_record( db, name );
if( !rec )
goto end;
r = MSI_RecordGetIStream( rec, 2, &stm );
msiobj_release( &rec->hdr );
if( r != ERROR_SUCCESS )
goto end;
r = OleLoadPicture( stm, 0, TRUE, &IID_IPicture, (LPVOID*) &pic );
IStream_Release( stm );
if( FAILED( r ) )
{
ERR("failed to load picture\n");
goto end;
}
r = IPicture_get_Handle( pic, (OLE_HANDLE*) &hOleBitmap );
if( FAILED( r ) )
{
ERR("failed to get bitmap handle\n");
goto end;
}
/* make the bitmap the desired size */
r = GetObjectW( hOleBitmap, sizeof bm, &bm );
if (r != sizeof bm )
{
ERR("failed to get bitmap size\n");
goto end;
}
if (flags & LR_DEFAULTSIZE)
{
cx = bm.bmWidth;
cy = bm.bmHeight;
}
srcdc = CreateCompatibleDC( NULL );
hOldSrcBitmap = SelectObject( srcdc, hOleBitmap );
destdc = CreateCompatibleDC( NULL );
hBitmap = CreateCompatibleBitmap( srcdc, cx, cy );
hOldDestBitmap = SelectObject( destdc, hBitmap );
StretchBlt( destdc, 0, 0, cx, cy,
srcdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
SelectObject( srcdc, hOldSrcBitmap );
SelectObject( destdc, hOldDestBitmap );
DeleteDC( srcdc );
DeleteDC( destdc );
end:
if ( pic )
IPicture_Release( pic );
return hBitmap;
}
static UINT msi_dialog_bitmap_control( msi_dialog *dialog, MSIRECORD *rec )
{
UINT cx, cy, flags, style, attributes;
msi_control *control;
LPWSTR text;
flags = LR_LOADFROMFILE;
style = SS_BITMAP | SS_LEFT | WS_GROUP;
attributes = MSI_RecordGetInteger( rec, 8 );
if( attributes & msidbControlAttributesFixedSize )
{
flags |= LR_DEFAULTSIZE;
style |= SS_CENTERIMAGE;
}
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 20
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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -