I am hooking CreateDialogIndirectParam. I want to do some manipulations over the dialog box, but but the width, height, and x and y positions are in dialog box units. Can someone explain how to convert them to screen coordinates?
Thanks in advance.
Try the MapDialogRect() function. I think it does what you think.
Remember that the mapping depends on the font used by the dialog, so the HWND must be that particular dialog.
Also from GetDialogBaseUnits():
pixelX = MulDiv(templateunitX, baseunitX, 4);
pixelY = MulDiv(templateunitY, baseunitY, 8);
Being baseunitX the value tmAveCharWidth and baseUnitY the value tmHeight returned by function GetTextMetrics(). You just need a HDC with the dialog font selected.
Related
I am currently using GDIGRAB to capture a window. The problem is, because of the border, the mouse cursor has an offset on its position.
The idea is to put a window as borderless so the offset won't appear anymore. Given the handle of the aimed process, how can I change a window from windowed to borderless ?
Don't tinker with another process' windows. Instead, get the border offset.
HWND window = ...;
RECT wndRect, clientRect;
GetWindowRect(window,&wndRect);
GetClientRect(window,&clientRect);
POINT borderOffset={clientRect.left,clientRect.top};
ClientToScreen(window,&borderOffset);
borderOffset.x-=wndRect.left;
borderOffset.y-=wndRect.top;
// borderOffset now contains the x and y offsets for the window
Currently i'm drawing the text from a textbox in my window. I successfully get the text i need to draw and it draws the text. It's ok.
Here's the problem: when i write something else in my input box and draw the text again (via button push), the new text is drawn right on top of the previous text as to be expected.
I'm new to all of this and i can't find a way to clear the previous text before drawing the new text.
Here's my code:
void DrawMyText(HWND hwnd) {
int iTextLength = GetWindowTextLength(hDrawInput) + 1;
char cDrawText[1000] = "";
HDC wdc = GetWindowDC(hwnd);
RECT canvas;
canvas.left = 168;
canvas.top = 108;
canvas.right = 500;
canvas.bottom = 500;
GetWindowText(hDrawInput, cDrawText, iTextLength);
SetTextColor(wdc, 0x00FF0066);
SetBkMode(wdc,TRANSPARENT);
DrawText(wdc, cDrawText, -1, &canvas, DT_LEFT);
DeleteDC(wdc);
}
Any tips on how to do this? I will gladly provide any additional information if needed. Thanks in advance!
DrawText is more like a spray can - it paints over top whatever is already there. I'd recommend switching to SetWindowText. The difference is DrawText is more like a canvas rendering call, and doesn't consider much about the type of control it's drawing to. SetWindowText is an explicit "set the text of this window to this specific value", and is specific to text-based controls. More to the point, it will replace the current text with the new text value.
If you absolutely must do it with DrawText (i.e. you prefer a canvas approach as above), then you'll have to manually clear the text area yourself with something like InvalidateRect() (using the RECT of the text area). Or, by drawing a rectangle equal in size to the text area and with the same color as the background. Let me know if that's not enough detail.
If some other window covers and then uncovers the place where you drew the text it will be gone! The illusion that windows can sit on top of each other is destroyed! Windows provides a scheme to overcome this problem but you are not cooperating with the scheme.
Paint your text only in response to the WM_PAINT message, using the BeginPaint and EndPaint API calls. On the button click just call InvalidateRect, which asks Windows to send you a WM_PAINT. BeginPaint erases your window just before you paint. So by putting your painting code in the right place - the WM_PAINT handler - you solve two problems: It erases any old text, and it repaints whenever your window is uncovered.
Someone can explain me how to convert dialog box units to screen coordinates values ?
I saw that there is MapDialogRect function, but its converting RECT, i want to convert the x,y and cx,cy values to screen coordinate values and i dont really understand how to achieve this.
Thanks in advance.
If you already have a window handle, then just use the MapDialogRect function. As others have noted, MapDialogRect takes a RECT, so if you don't have a RECT, you can create one.
RECT rc;
rc.left = x;
rc.top = y;
rc.right = x + cx;
rc.bottom = y + cy;
MapDialogRect(hdlg, &rc);
If your problem is that you don't have a dialog box handle in the first place, then the documentation for the MapDialogRect function tells you how to perform the calculations: Determine the the average character dimensions for the dialog box (which the documentation calls baseunitX and baseunitY) and then plug it into the formulas.
Note that this calculates the client rectangle of the dialog box. You still have to add non-client space. It's not clear what you're trying to do, so I don't know whether adding non-client space is appropriate or not.
I am quite desperate to resolve this very annoying issue :(
I am trying to display a child window on parent window. Some time the window need to be resized. But for some reason, when I using MoveWindow function it leaves blank space on the top of the parent window. I would like to present a picture here but I can not post a picture.
Here is the code example:
HWND hwnd // Comes from external function. Was defined as WS_CHILD previously
HWND hwndParent = ::GetParent(hwnd);
RECT parentRect = {0,0,0,0};
RECT childRect = {0,0,0,0};
::GetClientRect(hwndParent, &parentRect); // Suppose it returns {0,0,600,300}
BOOL ok = ::MoveWindow(hwnd, 0, 0, 600, 300, true);
::GetClientRect(hwnd, &childRect); // Will return {0,0,584,297}
WHY ?????
What am I doing wrong? Did I forgot some flags with window initialization?!
Rather than use GetClientRect, use GetWindowRect and MapWindowPoints(NULL,hwndParent,&parentRect,2) to adjust it to the parent window coordinates. GetWindowRect will include the non-client area that MoveWindow requires.
Edit: If you want a window that doesn't have a non-client area so the window rect and the client rect are the same size, you need to trim the window styles that you apply to the window. Avoid the WS_BORDER, WS_CAPTION, WS_DLGFRAME, WS_OVERLAPPED, WS_SIZEBOX, and WS_THICKFRAME styles.
MoveWindow updates window position, while GetClientRect gets a client-area part of the window, which does not have to be the same. If your window has non-client area, then everything is fine and works as expected.
If you are still under impression that child window does not fully cover parent's client area, then the spacing belongs to the child control/window, and you need to look for ways to remove it there (control flags, parameters etc).
MoveWindow operates on window coordinates -- including non-client area (borders, title bar, etc).
GetClientRect gets the area of the client portion of the window, ignoring borders, title bar, etc.
This is where the mismatch is. If you want to MoveWindow to a desired client size, you need to just AdjustWindowRect to try and predict what to pass into MoveWindow. Note that it's not always possible, and not always accurate. For example minimum / maximum sizes of windows, menus (which can wrap to multiple lines), etc.
The problem was WS_POPUP flag to the parent window.
Very strange. As far as I know it was not suppose to have such an effect.
Thanks for everyone!
I have made a window with CreateWindowEx() function, now how do i get the width and height from that window i created? This sounds very basic thing to do, but i just couldnt find any answer ;_;
This is needed because the window height is created automatically depending on how the Windows wants to create it.
Language C or C++
Use GetWindowRect. Subtract the right from the left to get the width and the bottom from the top to get the height.
RECT rect;
if(GetWindowRect(hwnd, &rect))
{
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
}
As a side note, if you'd like the client area instead of the entire window. You can use GetClientRect. For other information about the window you can use GetWindowInfo.
I believe you're looking for GetWindowInfo
Example:
HWND window = ::CreateWindowEx(...);
WINDOWINFO info;
if ( ::GetWindowInfo(window, &info) ) {
...
}
Have you tried GetWindowRect() or GetWindowInfo() which returns a WINDOWINFO structure?
Given there's no indication why you need the size, and that the size can change if the window style is set to include resizable attributes [and the user resizes the window using minimize/maximize/restore or drags a window edge], your safest choice is to include a message handler for WM_SIZE and use the wparam and lparam parameter values to determine window dimensions. This way, you'll always know the current size. WM_SIZE is called in the sequence of messages post window creation.