⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dialog.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
                             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 ********************************************/

struct msi_pathedit_info
{
    msi_dialog *dialog;
    msi_control *control;
    WNDPROC oldproc;
};

static LPWSTR msi_get_window_text( HWND hwnd )
{
    UINT sz, r;
    LPWSTR buf;

    sz = 0x20;
    buf = msi_alloc( sz*sizeof(WCHAR) );
    while ( buf )
    {
        r = GetWindowTextW( hwnd, buf, sz );
        if ( r < (sz - 1) )
            break;
        sz *= 2;
        buf = msi_realloc( buf, sz*sizeof(WCHAR) );
    }

    return buf;
}

static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control )
{
    LPWSTR prop, path;
    BOOL indirect;

    if (!control && !(control = msi_dialog_find_control_by_type( dialog, szPathEdit )))
       return;

    indirect = control->attributes & msidbControlAttributesIndirect;
    prop = msi_dialog_dup_property( dialog, control->property, indirect );
    path = msi_dialog_dup_property( dialog, prop, TRUE );

    SetWindowTextW( control->hwnd, path );
    SendMessageW( control->hwnd, EM_SETSEL, 0, -1 );

    msi_free( path );
    msi_free( prop );
}

/* FIXME: test when this should fail */
static BOOL msi_dialog_verify_path( LPWSTR path )
{
    if ( !lstrlenW( path ) )
        return FALSE;

    if ( PathIsRelativeW( path ) )
        return FALSE;

    return TRUE;
}

/* returns TRUE if the path is valid, FALSE otherwise */
static BOOL msi_dialog_onkillfocus( msi_dialog *dialog, msi_control *control )
{
    LPWSTR buf, prop;
    BOOL indirect;
    BOOL valid;

    indirect = control->attributes & msidbControlAttributesIndirect;
    prop = msi_dialog_dup_property( dialog, control->property, indirect );

    buf = msi_get_window_text( control->hwnd );

    if ( !msi_dialog_verify_path( buf ) )
    {
        /* FIXME: display an error message box */
        ERR("Invalid path %s\n", debugstr_w( buf ));
        valid = FALSE;
        SetFocus( control->hwnd );
    }
    else
    {
        valid = TRUE;
        MSI_SetPropertyW( dialog->package, prop, buf );
    }

    msi_dialog_update_pathedit( dialog, control );

    TRACE("edit %s contents changed, set %s\n", debugstr_w(control->name),
          debugstr_w(prop));

    msi_free( buf );
    msi_free( prop );

    return valid;
}

static LRESULT WINAPI MSIPathEdit_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    struct msi_pathedit_info *info = GetPropW(hWnd, szButtonData);
    LRESULT r = 0;

    TRACE("%p %04x %08x %08lx\n", hWnd, msg, wParam, lParam);

    if ( msg == WM_KILLFOCUS )
    {
        /* if the path is invalid, don't handle this message */
        if ( !msi_dialog_onkillfocus( info->dialog, info->control ) )
            return 0;
    }

    r = CallWindowProcW(info->oldproc, hWnd, msg, wParam, lParam);

    if ( msg == WM_NCDESTROY )
    {
        msi_free( info );
        RemovePropW( hWnd, szButtonData );
    }

    return r;
}

static UINT msi_dialog_pathedit_control( msi_dialog *dialog, MSIRECORD *rec )
{
    struct msi_pathedit_info *info;
    msi_control *control;
    LPCWSTR prop;

    info = msi_alloc( sizeof *info );
    if (!info)
        return ERROR_FUNCTION_FAILED;

    control = msi_dialog_add_control( dialog, rec, szEdit,
                                      WS_BORDER | WS_TABSTOP );
    control->attributes = MSI_RecordGetInteger( rec, 8 );
    prop = MSI_RecordGetString( rec, 9 );
    control->property = msi_dialog_dup_property( dialog, prop, FALSE );

    info->dialog = dialog;
    info->control = control;
    info->oldproc = (WNDPROC) SetWindowLongPtrW( control->hwnd, GWLP_WNDPROC,
                                                 (LONG_PTR)MSIPathEdit_WndProc );
    SetPropW( control->hwnd, szButtonData, info );

    msi_dialog_update_pathedit( dialog, control );

    return ERROR_SUCCESS;
}

/* 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, 0, szButton, name, text,
                                        style, group->parent->hwnd );
    if (!control)
        return ERROR_FUNCTION_FAILED;
    control->handler = msi_dialog_radiogroup_handler;

    if (!lstrcmpW(control->name, group->propval))
        SendMessageW(control->hwnd, BM_SETCHECK, BST_CHECKED, 0);

    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;
    msi_control *control;
    MSIQUERY *view = NULL;
    radio_button_group_descr group;
    MSIPACKAGE *package = dialog->package;
    WNDPROC oldproc;

    prop = MSI_RecordGetString( rec, 9 );

    TRACE("%p %p %s\n", dialog, rec, debugstr_w( prop ));

    /* Create parent group box to hold radio buttons */
    control = msi_dialog_add_control( dialog, rec, szButton, BS_OWNERDRAW|WS_GROUP );
    if( !control )
        return ERROR_FUNCTION_FAILED;

    oldproc = (WNDPROC) SetWindowLongPtrW( control->hwnd, GWLP_WNDPROC,
                                           (LONG_PTR)MSIRadioGroup_WndProc );
    SetPropW(control->hwnd, szButtonData, oldproc);
    SetWindowLongPtrW( control->hwnd, GWL_EXSTYLE, WS_EX_CONTROLPARENT );

    if( prop )
        control->property = strdupW( prop );

    /* query the Radio Button table for all control in this group */
    r = MSI_OpenQuery( package->db, &view, query, prop );
    if( r != ERROR_SUCCESS )
    {
        ERR("query failed for dialog %s radio group %s\n", 
            debugstr_w(dialog->name), debugstr_w(prop));
        return ERROR_INVALID_PARAMETER;
    }

    group.dialog = dialog;
    group.parent = control;
    group.attributes = MSI_RecordGetInteger( rec, 8 );
    group.propval = msi_dup_property( dialog->package, control->property );

    r = MSI_IterateRecords( view, 0, msi_dialog_create_radiobutton, &group );
    msiobj_release( &view->hdr );
    msi_free( group.propval );

    return r;
}

/******************** Selection Tree ***************************************/

struct msi_selection_tree_info
{
    msi_dialog *dialog;
    HWND hwnd;
    WNDPROC oldproc;
    HTREEITEM selected;
};

static void
msi_seltree_sync_item_state( HWND hwnd, MSIFEATURE *feature, HTREEITEM hItem )
{
    TVITEMW tvi;
    DWORD index = feature->Action;

    TRACE("Feature %s -> %d %d %d\n", debugstr_w(feature->Title),
        feature->Installed, feature->Action, feature->ActionRequest);

    if (index == INSTALLSTATE_UNKNOWN)
        index = INSTALLSTATE_ABSENT;

    tvi.mask = TVIF_STATE;
    tvi.hItem = hItem;
    tvi.state = INDEXTOSTATEIMAGEMASK( index );
    tvi.stateMask = TVIS_STATEIMAGEMASK;

    SendMessageW( hwnd, TVM_SETITEMW, 0, (LPARAM) &tvi );
}

static UINT
msi_seltree_popup_menu( HWND hwnd, INT x, INT y )
{
    HMENU hMenu;
    INT r;

    /* create a menu to display */
    hMenu = CreatePopupMenu();

    /* FIXME: load strings from resources */
    AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_LOCAL, "Install feature locally");
    AppendMenuA( hMenu, MF_GRAYED, 0x1000, "Install entire feature");
    AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ADVERTISED, "Install on demand");
    AppendMenuA( hMenu, MF_ENABLED, INSTALLSTATE_ABSENT, "Don't install");
    r = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
                        x, y, 0, hwnd, NULL );
    DestroyMenu( hMenu );
    return r;
}

static MSIFEATURE *
msi_seltree_feature_from_item( HWND hwnd, HTREEITEM hItem )
{
    TVITEMW tvi;

    /* get the feature from the item */
    memset( &tvi, 0, sizeof tvi );
    tvi.hItem = hItem;
    tvi.mask = TVIF_PARAM | TVIF_HANDLE;
    SendMessageW( hwnd, TVM_GETITEMW, 0, (LPARAM) &tvi );

    return (MSIFEATURE*) tvi.lParam;
}

static LRESULT
msi_seltree_menu( HWND hwnd, HTREEITEM hItem )
{
    struct msi_selection_tree_info *info;
    MSIFEATURE *feature;
    MSIPACKAGE *package;
    union {
        RECT rc;
        POINT pt[2];
        HTREEITEM hItem;
    } u;
    UINT r;

    info = GetPropW(hwnd, szButtonData);
    package = info->dialog->package;

    feature = msi_seltree_feature_from_item( hwnd, hItem );
    if (!feature)
    {
        ERR("item %p feature was NULL\n", hItem);
        return 0;
    }

    /* get the item's rectangle to put the menu just below it */
    u.hItem = hItem;
    SendMessageW( hwnd, TVM_GETITEMRECT, 0, (LPARAM) &u.rc );
    MapWindowPoints( hwnd, NULL, u.pt, 2 );

    r = msi_seltree_popup_menu( hwnd, u.rc.left, u.rc.top );

    switch (r)
    {
    case INSTALLSTATE_LOCAL:
    case INSTALLSTATE_ADVERTISED:
    case INSTALLSTATE_ABSENT:
        msi_feature_set_state( feature, r );
        break;
    default:
        FIXME("select feature and all children\n");
    }

    /* update */
    msi_seltree_sync_item_state( hwnd, feature, hItem );
    ACTION_UpdateComponentStates( package, feature->Feature );

    return 0;
}

static MSIFEATURE *msi_seltree_get_selected_feature( msi_control *control )
{
    struct msi_selection_tree_info *info = GetPropW(control->hwnd, szButtonData);
    return msi_seltree_feature_from_item( control->hwnd, info->selected );
}

static LRESULT WINAPI
MSISelectionTree_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    struct msi_selection_tree_info *info;
    TVHITTESTINFO tvhti;
    HRESULT r;

    TRACE("%p %04x %08x %08lx\n", hWnd, msg, wParam, lParam);

    info = GetPropW(hWnd, szButtonData);

    switch( msg )
    {
    case WM_LBUTTONDOWN:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -