简体   繁体   English

C ++获取对话框控件的位置和大小

[英]C++ Get the position and size of a dialog control

I'm using Visual Studio 2015 C++ and have a dialog box defined in an .rc-file: 我正在使用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

The control I'm interested in is the picturebox "IDC_SENSOR" (last entry), which is defined at/as 41,62,256,76. 我感兴趣的控件是图片框“ IDC_SENSOR”(最后一个条目),其定义为41,62,256,76。 But on screen that proportions are different, probably due to the Dynamic Dialog Layout. 但是在屏幕上,比例可能有所不同,这可能是由于“动态对话框布局”所致。 So I want to know the exact position and size of that box whithin the dialogbox, but I cannot get those parameters. 因此,我想知道对话框中该框的确切位置和大小,但是我无法获取这些参数。

The procedure which it is used in: 它用于以下过程:

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));
    }
}

The x<200 in the for-loop should be set to the width of the picturebox. for循环中的x <200应该设置为图片框的宽度。

How can I get those dimensions? 如何获得这些尺寸?

I hope this is enough info(?). 我希望这是足够的信息(?)。

Greetings, CJ. 问候,CJ。

The control I'm interested in is the picturebox "IDC_SENSOR" (last entry), which is defined at/as 41,62,256,76. 我感兴趣的控件是图片框“ IDC_SENSOR”(最后一个条目),其定义为41,62,256,76。 But on screen that proportions are different, probably due to the Dynamic Dialog Layout. 但是在屏幕上,比例可能有所不同,这可能是由于“动态对话框布局”所致。

Yes, that's correct. 对,那是正确的。 Coordinates in dialog resources are specified in DLUs (dialog units). 对话框资源中的坐标以DLU(对话单位)指定。 You can convert dialog units into pixels by calling the MapDialogRect function. 您可以通过调用MapDialogRect函数将对话框单位转换为像素。

But that's not really what you want to do here, because you don't want to hard-code the dialog coordinates in your code. 但这并不是您真正想要的,因为您不想在代码中对对话框坐标进行硬编码。 If you change the resource file, you want your code to continue to work. 如果更改资源文件,则希望代码继续工作。

I want to know the exact position and size of that box whithin the dialogbox 我想知道对话框中该框的确切位置和大小

What you really need is to obtain the coordinates of the control on the screen, in pixels. 您真正需要的是获取屏幕上控件的坐标(以像素为单位)。 There are two functions specifically designed for that purpose: 为此专门设计了两个功能:

  • GetClientRect tells you the window's rectangle in client coordinates. GetClientRect告诉您客户端坐标中窗口的矩形。 For a child window, such as a control, the upper-left corner will always be (0, 0), and the lower-right corner will tell you the width and height. 对于子窗口(例如控件),左上角始终为(0,0),而右下角将告诉您宽度和高度。
  • GetWindowRect tells you the window's rectangle in screen coordinates. GetWindowRect告诉您屏幕坐标中的窗口矩形。 These are "absolute" coordinates, relative to the virtual screen. 这些是相对于虚拟屏幕的“绝对”坐标。 Unlike the client rectangle, the window rectangle also includes the size of the window's non-client area. 与客户矩形不同,窗口矩形还包括窗口非客户区域的大小。

You probably already know this, but the width of this rectangle is determined by subtracting its left bound from its right bound. 您可能已经知道这一点,但是此矩形的宽度是通过从其右边界减去其左边界来确定的。 Similarly, the height is determined by subtracting its top bound from its bottom bound. 类似地,通过从其底部边界减去其顶部边界来确定高度。 Or, if you use the MFC wrapper class, CRect (which is interchangeable everywhere with RECT , including when calling the two above functions), you can just call the Width and Height member functions. 或者,如果使用MFC包装器类CRect (可在所有地方与RECT互换,包括调用上述两个函数时),则可以仅调用WidthHeight成员函数。

As for your particular use-case, since you're calling GetDC on the child window itself, you're getting a client DC, and you would need client coordinates, so you would call GetClientRect . 至于您的特定用例,由于您是在子窗口本身上调用GetDC ,因此您将获得一个客户端DC,并且需要客户端坐标,因此您将调用GetClientRect Simple. 简单。 Except that your code is wrong. 除了您的代码是错误的。 You are obtaining a DC and painting outside of a WM_PAINT message handler, which means that anything you paint is subject to being erased at arbitrary intervals. 您将在WM_PAINT消息处理程序之外获得DC和绘画,这意味着您绘画的任何内容都会以任意间隔被擦除。 All drawing should be done in response to a WM_PAINT message. 应响应WM_PAINT消息完成所有绘图。

A simple way of accomplishing this in your case would be to set the SS_OWNERDRAW style for your IDC_SENSOR control. 在您的情况下,完成此操作的一种简单方法是为IDC_SENSOR控件设置SS_OWNERDRAW样式。 This puts the parent dialog in charge of drawing the control's contents. 这使父对话框负责绘制控件的内容。 It will receive WM_DRAWITEM messages when the child control needs to be drawn. 当需要绘制子控件时,它将接收WM_DRAWITEM消息。 Add an OnDrawItem handler and do your drawing in there. 添加一个OnDrawItem处理程序并在其中进行绘图。 The DRAWITEMSTRUCT passed as a parameter will tell you the rectangle into which you should draw ( rcItem ). 作为参数传递的DRAWITEMSTRUCT将告诉您应绘制到的矩形( rcItem )。

Finally, I should note that SetPixelV is quite slow. 最后,我应该注意SetPixelV相当慢。 If it's fast enough for you, just ignore the rest of this comment. 如果速度足够快,请忽略此注释的其余部分。 But if drawing on the screen is really slow, then you should consider creating and caching a bitmap object. 但是,如果在屏幕上绘制的速度确实很慢,则应考虑创建并缓存位图对象。 Draw into that bitmap, setting its individual pixels, and then simply blit that bitmap onto your control's device context. 绘制到该位图中,设置其单个像素,然后只需将该位图blit到控件的设备上下文中即可。 Accessing and manipulating the individual pixels of an offscreen bitmap is much faster. 访问和处理屏幕外位图的各个像素快得多。

I've managed to retrieve the details with GetClientRect: 我设法用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));
            }

        }
    }

So I mark this question as answered! 因此,我将此问题标记为已回答!

I'm not quite sure if this is the 'correct' way, I'm lacking the experience for that. 我不太确定这是否是“正确”的方法,我缺乏经验。 But it works, and then it should be fairly ok :) 但这有效,然后应该还可以:)

Instead of drawing (directly) into the picturebox, I'm gonna use a bitmap as suggested. 与其(直接)画入图片框,不如我建议使用位图。 Thats indeed better and easier to work with. 那确实更好,更容易使用。

What I now need to discover is how to update the dialogbox the proper way with that bitmap. 我现在需要发现的是如何使用该位图以正确的方式更新对话框。 As Cody stated such drawing should not be done whithin this routine, but handled as a separate OnDrawItem instruction. 正如科迪所说,这种绘制不应在此例程中完成,而应作为单独的OnDrawItem指令进行处理。 Hmm, more to learn. 嗯,还有更多要学习的。

Thanx and greetins, CJ Thanx和greetins,CJ

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM