【问题标题】:C++ Get the position and size of a dialog controlC++ 获取对话框控件的位置和大小
【发布时间】:2016-10-02 09:27:48
【问题描述】:

我正在使用 Visual Studio 2015 C++,并在 .rc 文件中定义了一个对话框:

IDD_SERIALCTRLDEMO_DIALOG DIALOGEX 0, 0, 313, 164
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "SerialCtrlDemo"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    LTEXT           "Serial Number:",IDC_STATIC,14,10,48,8
    COMBOBOX        IDC_COMBO_SN,66,8,48,55,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
    LTEXT           "Baud Rate:",IDC_STATIC,135,10,37,8
    COMBOBOX        IDC_COMBO_BR,176,8,48,55,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
    LTEXT           "Read:",IDC_STATIC,11,51,20,8
    PUSHBUTTON      "Open",IDC_BUTTON_OPEN,242,7,50,14
    LISTBOX         IDC_LIST_READ,11,62,23,76,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_WRITE,11,34,237,14,ES_AUTOHSCROLL
    PUSHBUTTON      "Write",IDC_BUTTON_WR,252,33,46,14
    GROUPBOX        "",IDC_STATIC,7,0,294,25
    GROUPBOX        "",IDC_STATIC,7,26,296,117
    LTEXT           "",IDC_STATIC_INFO,11,150,287,8
    CONTROL         "",IDC_SENSOR,"Static",SS_BLACKRECT,41,62,256,76
END

enter code here

我感兴趣的控件是图片框“IDC_SENSOR”(最后一个条目),它定义在/为 41,62,256,76。但在屏幕上,比例不同,可能是由于动态对话框布局。 所以我想知道对话框中那个框的确切位置和大小,但我无法获得这些参数。

使用的程序:

void CSerialCtrlDemoDlg::OnEventRead(char *inPacket,int inLength)
}
    int x=0;


    m_listboxRead.AddString(inPacket);      // display the incomming data in the 'Read' listbox

    CString str;                    // display the # of data's in 'Info'
    str.Format("%d bytes read",inLength);
    m_staticInfo.SetWindowText(str);

    CWnd *cWndSensor = GetDlgItem(IDC_SENSOR);  // show the fluctuation in the Picturebox 
    CDC *pDC = cWndSensor->GetDC();

    for (x = 0; x < 200; x++)
    {
        pDC->SetPixelV(x, 10, RGB(rand() % 255, 0, 0));
    }
}

for循环中的x

如何获得这些尺寸?

我希望这是足够的信息(?)。

您好,CJ。

【问题讨论】:

    标签: c++ dynamic dialog size picturebox


    【解决方案1】:

    我感兴趣的控件是图片框“IDC_SENSOR”(最后一个条目),它定义在/为 41,62,256,76。但在屏幕上,比例不同,可能是由于动态对话框布局。

    是的,没错。对话资源中的坐标以 DLU(对话单元)指定。您可以通过调用MapDialogRect 函数将对话框单位转换为像素。

    但这并不是您真正想要在此处执行的操作,因为您不想在代码中硬编码对话框坐标。如果您更改资源文件,您希望您的代码继续工作。

    我想知道对话框中那个框的确切位置和大小

    您真正需要的是获取屏幕上控件的坐标,以像素为单位。有两个专门为此目的设计的函数:

    • GetClientRect 告诉您 client 坐标中的窗口矩形。对于子窗口,比如控件,左上角永远是(0, 0),右下角会告诉你宽度和高度。
    • GetWindowRect 告诉你窗口在 screen 坐标中的矩形。这些是相对于虚拟屏幕的“绝对”坐标。与客户矩形不同,窗口矩形还包括窗口非客户区的大小。

    您可能已经知道这一点,但是这个矩形的宽度是通过从它的右边界减去它的左边界来确定的。类似地,高度是通过从其底部边界中减去其顶部边界来确定的。或者,如果您使用 MFC 包装类 CRect(可与 RECT 在任何地方互换,包括调用上述两个函数时),您可以只调用 WidthHeight 成员函数。

    至于您的特定用例,由于您在子窗口本身上调用 GetDC,因此您将获得客户端 DC,并且您将需要客户端坐标,因此您将调用 GetClientRect。简单的。除了你的代码是错误的。您正在获得一个 DC 并在 WM_PAINT 消息处理程序的外部进行绘制,这意味着您绘制的任何内容都会以任意间隔被擦除。所有绘图都应响应WM_PAINT 消息完成。

    在您的情况下,完成此操作的一种简单方法是为您的IDC_SENSOR 控件设置SS_OWNERDRAW 样式。这使父对话框负责绘制控件的内容。当需要绘制子控件时,它将收到WM_DRAWITEM 消息。添加一个OnDrawItem 处理程序并在其中进行绘图。作为参数传递的DRAWITEMSTRUCT 将告诉您应该绘制的矩形 (rcItem)。

    最后,我应该注意到SetPixelV 非常慢。如果它对您来说足够快,请忽略此评论的其余部分。但是如果在屏幕上绘图真的很慢,那么你应该考虑创建和缓存一个位图对象。绘制到该位图中,设置其各个像素,然后将该位图简单地 blit 到控件的设备上下文中。访问和操作屏幕外位图的单个像素要快得多

    【讨论】:

    • 你好科迪,谢谢你的回答。我得到了它的感觉,但我现在需要在我的代码中得到它。这需要一些试验和探索。自从我在 Windows 中编程以来已经有一段时间了,它确实需要一些“其他”的想法。 - 问候,CJ。
    【解决方案2】:

    我已设法使用 GetClientRect 检索详细信息:

    void CSerialCtrlDemoDlg::OnEventRead(char *inPacket,int inLength)
    
        {
            int i = 0;
            int j = 0;
            int x = 0;
            int y = 0;
            int w = 100;
            int h = 50;
    
            RECT sensorRect;
    
            CWnd *cWndSensor = GetDlgItem(IDC_SENSOR);
            CDC *pDC = cWndSensor->GetDC();
    
            cWndSensor->GetClientRect(&sensorRect);
    
            x = sensorRect.left;
            y = sensorRect.top;
            w = sensorRect.right - x;
            h = sensorRect.bottom - y;
    
    
            for (i = 0; i < w; i++)    // this fills the picturebox (for test only)
            {
                for (j = 0; j < h; j++)
                {
                    pDC->SetPixelV(i, j, RGB(rand() % 255, 0, 0));
                }
    
            }
        }
    

    所以我将此问题标记为已回答!

    我不太确定这是否是“正确”的方式,我缺乏这方面的经验。但它有效,然后它应该是相当好的:)

    我将按照建议使用位图,而不是(直接)绘制到图片框中。这确实更好,更容易使用。

    我现在需要发现的是如何使用该位图以正确的方式更新对话框。正如 Cody 所说,此类绘图不应在此例程中完成,而应作为单独的 OnDrawItem 指令处理。嗯,要学习更多。

    谢谢你,CJ

    【讨论】:

    • 很高兴看到您成功了!这段代码对我来说看起来很合理。从风格上讲,我的小问题是你没有按照 1990 年的规范编写 C,所以你应该更喜欢在初始化时声明变量,而不是在函数顶部列出一大堆默认初始化的变量。换句话说,当您分配实际值时,您检索客户矩形之后声明 x、y、w 和 h。但这不是正确性问题,只是风格问题。
    • 对于 OnDrawItem,这就是您在 MFC 中所有者绘制控件的方式。确实,总是有更多的东西要学。所有者绘图是 Windows 编程世界中一个相当基本的主题,但它仍然是一个高级主题。 MSDN 上的文档很少,但有 this introduction。您需要自己将原始 Win32 习语翻译成 MFC 习语。如果您决定深入研究,但遇到困难,您可以提出一个新问题。
    猜你喜欢
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    相关资源
    最近更新 更多