2013-03-13 64 views
2

當我在運行時在對話框窗口中將BS_AUTO3STATE樣式添加到默認樣式複選框時;3狀態複選框Win32運行時

this->Style |= BS_AUTO3STATE; // wrapper of Get/SetWindowLongPtr, ignore the specifics 

..它變成了一個組框,而不是一個三態複選框。我究竟做錯了什麼?

我有錯誤的控制風格嗎?

回答

7

此問題是由於BS_Xxx值實際上未在標頭中定義爲位標誌的事實引起的。相反,他們的價值觀只是線性增加:

#define BS_PUSHBUTTON  0x00000000L 
#define BS_DEFPUSHBUTTON 0x00000001L 
#define BS_CHECKBOX   0x00000002L 
#define BS_AUTOCHECKBOX  0x00000003L 
#define BS_RADIOBUTTON  0x00000004L 
#define BS_3STATE   0x00000005L 
#define BS_AUTO3STATE  0x00000006L 
#define BS_GROUPBOX   0x00000007L 
#define BS_USERBUTTON  0x00000008L 
#define BS_AUTORADIOBUTTON 0x00000009L 
// ... and so on 

注意BS_GROUPBOX(這是你得到不想要的樣式)等於0x7。您的控制權以該樣式標誌設置結束,因爲您正在設置標誌的組合,其值爲0x7。不幸的是,你不能只將OR的標誌放在一起,並得到你想要的結果。

取而代之,您必須使用BS_TYPEMASK標誌清除當前按鈕樣式,然後設置您想要的各個BS_Xxx標誌。對於正常的複選框,可能是BS_AUTOCHECKBOX;對於三態複選框,即BS_AUTO3STATE

工作示例代碼:

void ToggleCheckboxCtrl(HWND hwndCheckBox) 
{ 
    // Retrieve the control's current styles. 
    LONG_PTR styles = GetWindowLongPtr(hwndCheckBox, GWL_STYLE); 

    // Remove any button styles that may be set so they don't interfere 
    // (but maintain any general window styles that are also set). 
    styles &= ~BS_TYPEMASK; 

    // Just for example purposes, we're maintain our last state as a static var. 
    // In the real code, you probably have a better way of determining this! 
    static bool isRegularCheckBox = true; 
    if (isRegularCheckBox) 
    { 
     // If we're a regular checkbox, toggle us to a 3-state checkbox. 
     styles |= BS_AUTO3STATE; 
    } 
    else 
    { 
     // Otherwise, we want to go back to being a regular checkbox. 
     styles |= BS_AUTOCHECKBOX; 
    } 
    isSet = !isSet; 

    // Update the control's styles. 
    // (You'll also need to force a repaint to see your changes.) 
    SetWindowLongPtr(hwndCheckBox, GWL_STYLE, styles); 
} 

間諜++實用程序(與Visual Studio捆綁)可以找出切換窗口樣式時什麼錯誤不可缺少的小工具。運行你的應用程序,並使用Spy ++來定位窗口並枚舉它的當前樣式。然後更改樣式,使用Spy ++轉儲新樣式,並查看出了什麼問題。