2013-03-13 61 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 ++转储新样式,并查看出了什么问题。