dialog.c
来自「一个类似windows」· C语言 代码 · 共 2,228 行 · 第 1/5 页
C
2,228 行
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2005 Mike McCormack for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "wingdi.h"
#include "msi.h"
#include "msipriv.h"
#include "msidefs.h"
#include "ocidl.h"
#include "olectl.h"
#include "richedit.h"
#include "commctrl.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
struct msi_control_tag;
typedef struct msi_control_tag msi_control;
typedef UINT (*msi_handler)( msi_dialog *, msi_control *, WPARAM );
struct msi_control_tag
{
struct list entry;
HWND hwnd;
msi_handler handler;
LPWSTR property;
LPWSTR value;
HBITMAP hBitmap;
HICON hIcon;
LPWSTR tabnext;
WCHAR name[1];
};
typedef struct msi_font_tag
{
struct msi_font_tag *next;
HFONT hfont;
WCHAR name[1];
} msi_font;
struct msi_dialog_tag
{
MSIPACKAGE *package;
msi_dialog_event_handler event_handler;
BOOL finished;
INT scale;
DWORD attributes;
HWND hwnd;
LPWSTR default_font;
msi_font *font_list;
struct list controls;
HWND hWndFocus;
LPWSTR control_default;
LPWSTR control_cancel;
WCHAR name[1];
};
typedef UINT (*msi_dialog_control_func)( msi_dialog *dialog, MSIRECORD *rec );
struct control_handler
{
LPCWSTR control_type;
msi_dialog_control_func func;
};
typedef struct
{
msi_dialog* dialog;
msi_control *parent;
DWORD attributes;
} radio_button_group_descr;
const WCHAR szMsiDialogClass[] = {
'M','s','i','D','i','a','l','o','g','C','l','o','s','e','C','l','a','s','s',0
};
const WCHAR szMsiHiddenWindow[] = {
'M','s','i','H','i','d','d','e','n','W','i','n','d','o','w',0 };
static const WCHAR szStatic[] = { 'S','t','a','t','i','c',0 };
static const WCHAR szButton[] = { 'B','U','T','T','O','N', 0 };
static const WCHAR szButtonData[] = { 'M','S','I','D','A','T','A',0 };
static const WCHAR szText[] = { 'T','e','x','t',0 };
static const WCHAR szPushButton[] = { 'P','u','s','h','B','u','t','t','o','n',0 };
static const WCHAR szLine[] = { 'L','i','n','e',0 };
static const WCHAR szBitmap[] = { 'B','i','t','m','a','p',0 };
static const WCHAR szCheckBox[] = { 'C','h','e','c','k','B','o','x',0 };
static const WCHAR szScrollableText[] = {
'S','c','r','o','l','l','a','b','l','e','T','e','x','t',0 };
static const WCHAR szComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
static const WCHAR szEdit[] = { 'E','d','i','t',0 };
static const WCHAR szMaskedEdit[] = { 'M','a','s','k','e','d','E','d','i','t',0 };
static const WCHAR szPathEdit[] = { 'P','a','t','h','E','d','i','t',0 };
static const WCHAR szProgressBar[] = {
'P','r','o','g','r','e','s','s','B','a','r',0 };
static const WCHAR szRadioButtonGroup[] = {
'R','a','d','i','o','B','u','t','t','o','n','G','r','o','u','p',0 };
static const WCHAR szIcon[] = { 'I','c','o','n',0 };
static const WCHAR szSelectionTree[] = {
'S','e','l','e','c','t','i','o','n','T','r','e','e',0 };
static UINT msi_dialog_checkbox_handler( msi_dialog *, msi_control *, WPARAM );
static void msi_dialog_checkbox_sync_state( msi_dialog *, msi_control * );
static UINT msi_dialog_button_handler( msi_dialog *, msi_control *, WPARAM );
static UINT msi_dialog_edit_handler( msi_dialog *, msi_control *, WPARAM );
static UINT msi_dialog_radiogroup_handler( msi_dialog *, msi_control *, WPARAM param );
static UINT msi_dialog_evaluate_control_conditions( msi_dialog *dialog );
static LRESULT WINAPI MSIRadioGroup_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
/* dialog sequencing */
#define WM_MSI_DIALOG_CREATE (WM_USER+0x100)
#define WM_MSI_DIALOG_DESTROY (WM_USER+0x101)
static DWORD uiThreadId;
static HWND hMsiHiddenWindow;
static INT msi_dialog_scale_unit( msi_dialog *dialog, INT val )
{
return (dialog->scale * val + 5) / 10;
}
static msi_control *msi_dialog_find_control( msi_dialog *dialog, LPCWSTR name )
{
msi_control *control;
if( !name )
return NULL;
LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
if( !strcmpW( control->name, name ) ) /* FIXME: case sensitive? */
return control;
return NULL;
}
static msi_control *msi_dialog_find_control_by_hwnd( msi_dialog *dialog, HWND hwnd )
{
msi_control *control;
LIST_FOR_EACH_ENTRY( control, &dialog->controls, msi_control, entry )
if( hwnd == control->hwnd )
return control;
return NULL;
}
static LPWSTR msi_get_deformatted_field( MSIPACKAGE *package, MSIRECORD *rec, int field )
{
LPCWSTR str = MSI_RecordGetString( rec, field );
LPWSTR ret = NULL;
if (str)
deformat_string( package, str, &ret );
return ret;
}
/*
* msi_dialog_get_style
*
* Extract the {\style} string from the front of the text to display and
* update the pointer.
*/
static LPWSTR msi_dialog_get_style( LPCWSTR p, LPCWSTR *rest )
{
LPWSTR ret = NULL;
LPCWSTR q, i;
DWORD len;
*rest = p;
if( !p )
return ret;
if( *p++ != '{' )
return ret;
q = strchrW( p, '}' );
if( !q )
return ret;
if( *p == '\\' || *p == '&' )
p++;
/* little bit of sanity checking to stop us getting confused with RTF */
for( i=p; i<q; i++ )
if( *i == '}' || *i == '\\' )
return ret;
*rest = ++q;
len = q - p;
ret = msi_alloc( len*sizeof(WCHAR) );
if( !ret )
return ret;
memcpy( ret, p, len*sizeof(WCHAR) );
ret[len-1] = 0;
return ret;
}
static UINT msi_dialog_add_font( MSIRECORD *rec, LPVOID param )
{
msi_dialog *dialog = param;
msi_font *font;
LPCWSTR face, name;
LOGFONTW lf;
INT style;
HDC hdc;
/* create a font and add it to the list */
name = MSI_RecordGetString( rec, 1 );
font = msi_alloc( sizeof *font + strlenW( name )*sizeof (WCHAR) );
strcpyW( font->name, name );
font->next = dialog->font_list;
dialog->font_list = font;
memset( &lf, 0, sizeof lf );
face = MSI_RecordGetString( rec, 2 );
lf.lfHeight = MSI_RecordGetInteger( rec, 3 );
style = MSI_RecordGetInteger( rec, 5 );
if( style & msidbTextStyleStyleBitsBold )
lf.lfWeight = FW_BOLD;
if( style & msidbTextStyleStyleBitsItalic )
lf.lfItalic = TRUE;
if( style & msidbTextStyleStyleBitsUnderline )
lf.lfUnderline = TRUE;
if( style & msidbTextStyleStyleBitsStrike )
lf.lfStrikeOut = TRUE;
lstrcpynW( lf.lfFaceName, face, LF_FACESIZE );
/* adjust the height */
hdc = GetDC( dialog->hwnd );
if (hdc)
{
lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC( dialog->hwnd, hdc );
}
font->hfont = CreateFontIndirectW( &lf );
TRACE("Adding font style %s\n", debugstr_w(font->name) );
return ERROR_SUCCESS;
}
static msi_font *msi_dialog_find_font( msi_dialog *dialog, LPCWSTR name )
{
msi_font *font;
for( font = dialog->font_list; font; font = font->next )
if( !strcmpW( font->name, name ) ) /* FIXME: case sensitive? */
break;
return font;
}
static UINT msi_dialog_set_font( msi_dialog *dialog, HWND hwnd, LPCWSTR name )
{
msi_font *font;
font = msi_dialog_find_font( dialog, name );
if( font )
SendMessageW( hwnd, WM_SETFONT, (WPARAM) font->hfont, TRUE );
else
ERR("No font entry for %s\n", debugstr_w(name));
return ERROR_SUCCESS;
}
static UINT msi_dialog_build_font_list( msi_dialog *dialog )
{
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ',
'F','R','O','M',' ','`','T','e','x','t','S','t','y','l','e','`',' ',0
};
UINT r;
MSIQUERY *view = NULL;
TRACE("dialog %p\n", dialog );
r = MSI_OpenQuery( dialog->package->db, &view, query );
if( r != ERROR_SUCCESS )
return r;
r = MSI_IterateRecords( view, NULL, msi_dialog_add_font, dialog );
msiobj_release( &view->hdr );
return r;
}
static msi_control *msi_dialog_create_window( msi_dialog *dialog,
MSIRECORD *rec, LPCWSTR szCls, LPCWSTR name, LPCWSTR text,
DWORD style, HWND parent )
{
DWORD x, y, width, height;
LPWSTR font = NULL, title_font = NULL;
LPCWSTR title = NULL;
msi_control *control;
style |= WS_CHILD;
control = msi_alloc( sizeof *control + strlenW(name)*sizeof(WCHAR) );
strcpyW( control->name, name );
list_add_head( &dialog->controls, &control->entry );
control->handler = NULL;
control->property = NULL;
control->value = NULL;
control->hBitmap = NULL;
control->hIcon = NULL;
control->tabnext = strdupW( MSI_RecordGetString( rec, 11) );
x = MSI_RecordGetInteger( rec, 4 );
y = MSI_RecordGetInteger( rec, 5 );
width = MSI_RecordGetInteger( rec, 6 );
height = MSI_RecordGetInteger( rec, 7 );
x = msi_dialog_scale_unit( dialog, x );
y = msi_dialog_scale_unit( dialog, y );
width = msi_dialog_scale_unit( dialog, width );
height = msi_dialog_scale_unit( dialog, height );
if( text )
{
deformat_string( dialog->package, text, &title_font );
font = msi_dialog_get_style( title_font, &title );
}
control->hwnd = CreateWindowW( szCls, title, style,
x, y, width, height, parent, NULL, NULL, NULL );
TRACE("Dialog %s control %s hwnd %p\n",
debugstr_w(dialog->name), debugstr_w(text), control->hwnd );
msi_dialog_set_font( dialog, control->hwnd,
font ? font : dialog->default_font );
msi_free( title_font );
msi_free( font );
return control;
}
static MSIRECORD *msi_get_binary_record( MSIDATABASE *db, LPCWSTR name )
{
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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?