how to use DrawText() to write text in a given window whose handle is known? - winapi

I want to know how to write text on a particular window starting at a given location in the window using the Windows API.
For example if the coordinates within the window where the text is to be written are (x,y) = (40,10) then what do I need to do to write a line of text to a particular window at that location in the window?

Suppose your window name is "hwnd" and the text which u want to write on that window at x,y coordinate is say stored in "message" where
LPCWSTR message=L"My First Window"; then
RECT rect;
HDC wdc = GetWindowDC(hwnd);
GetClientRect (bgHandle, &rect) ;
SetTextColor(wdc, 0x00000000);
SetBkMode(wdc,TRANSPARENT);
rect.left=40;
rect.top=10;
DrawText( wdc, message, -1, &rect, DT_SINGLELINE | DT_NOCLIP ) ;
DeleteDC(wdc);
Thats it.. remember this is just one example.

I am hoping this a more complete answer...
void OnPaint(HWND hWnd)
{
RECT rect;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);
SetTextColor(hdc, RGB(0xFF, 0x00, 0x00));
SetBkMode(hdc, TRANSPARENT);
rect.left = 40;
rect.top = 10;
DrawText(hdc, L"Hello World!", -1, &rect, DT_SINGLELINE | DT_NOCLIP);
SelectObject(hdc, oldPen);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
This would then be called from the WM_PAINT message in the WndProc.

Related

C++ Win32 API - CreateFont(): the documentation example is confusing

The Win32 API function CreateFont() documentation has a confusing example:
As you can see below, they made 3 calls to CreateFont() using the same HANDLE (hFont).. and at the end they have called DeleteObject() for the last one only... but before EndPaint() (while the font is being select to the DC).
I've found this example so misleading about the way DeleteObject() must be used.
I hope if someone could confirm or justify this code.
The example:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
{
RECT rect;
HBRUSH hBrush;
HFONT hFont;
hdc = BeginPaint(hWnd, &ps);
//Logical units are device dependent pixels, so this will create a handle to a logical font that is 48 pixels in height.
//The width, when set to 0, will cause the font mapper to choose the closest matching value.
//The font face name will be Impact.
hFont = CreateFont(48,0,0,0,FW_DONTCARE,FALSE,TRUE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, VARIABLE_PITCH,TEXT("Impact"));
SelectObject(hdc, hFont);
//Sets the coordinates for the rectangle in which the text is to be formatted.
SetRect(&rect, 100,100,700,200);
SetTextColor(hdc, RGB(255,0,0));
DrawText(hdc, TEXT("Drawing Text with Impact"), -1,&rect, DT_NOCLIP);
//Logical units are device dependent pixels, so this will create a handle to a logical font that is 36 pixels in height.
//The width, when set to 20, will cause the font mapper to choose a font which, in this case, is stretched.
//The font face name will be Times New Roman. This time nEscapement is at -300 tenths of a degree (-30 degrees)
hFont = CreateFont(36,20,-300,0,FW_DONTCARE,FALSE,TRUE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, VARIABLE_PITCH,TEXT("Times New Roman"));
SelectObject(hdc,hFont);
//Sets the coordinates for the rectangle in which the text is to be formatted.
SetRect(&rect, 100, 200, 900, 800);
SetTextColor(hdc, RGB(0,128,0));
DrawText(hdc, TEXT("Drawing Text with Times New Roman"), -1,&rect, DT_NOCLIP);
//Logical units are device dependent pixels, so this will create a handle to a logical font that is 36 pixels in height.
//The width, when set to 10, will cause the font mapper to choose a font which, in this case, is compressed.
//The font face name will be Arial. This time nEscapement is at 250 tenths of a degree (25 degrees)
hFont = CreateFont(36,10,250,0,FW_DONTCARE,FALSE,TRUE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY, VARIABLE_PITCH,TEXT("Arial"));
SelectObject(hdc,hFont);
//Sets the coordinates for the rectangle in which the text is to be formatted.
SetRect(&rect, 500, 200, 1400, 600);
SetTextColor(hdc, RGB(0,0,255));
DrawText(hdc, TEXT("Drawing Text with Arial"), -1,&rect, DT_NOCLIP);
DeleteObject(hFont);
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

C++ Win32: HDC's, HWND's, SelectObject, and GetObject

I'm new to win32 and there are some concepts I haven't fully grasped. For one, the difference between HDC and HWND. I understand (or think I understand) that they're handles to a objects and that hdc's can be derived from hwnd's. Like in the case of BeginPaint:
hdc = BeginPaint(hWnd, &ps);
But i don't fully understand what seperates each as certain methods have hdc as parameters and some use hwnd
Secondly, I'm not sure what SelectObject and GetObject do. I think that they associate handles with various objects, like in the case of this bitmap drawing function:
BOOL DrawBitmap (HDC hDC, INT x, INT y, INT width, INT height, HBITMAP hBitmap,
DWORD dwROP)
{
HDC hDCBits;
BITMAP Bitmap;
BOOL bResult;
hDCBits = CreateCompatibleDC(hDC);
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
SelectObject(hDCBits, hBitmap);
bResult = StretchBlt(hDC, x, y, width, height,hDCBits, 0, 0, Bitmap.bmWidth,
Bitmap.bmHeight, dwROP);
DeleteDC(hDCBits);
return bResult;
}
But despite all of this I don't understand exactly what they do or how they work. Thanks, in advance.

Win32 can't get SetBkMode Transparency to work

I am writing a simple program, that prints some text on the screen, overlaying the other windows.
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
HWND hwnd = GetDesktopWindow();
HDC hdc;
RECT rect;
//LPRECT rect = new RECT;
wchar_t text[] = L"test";
GetClientRect(hwnd, &rect);
do{
hdc = GetWindowDC(hwnd);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(100, 100, 100));
DrawText(hdc, text, -1, &rect, DT_NOCLIP);
ReleaseDC(hwnd, hdc);
Sleep(15);
} while (1);
return 0;
}
The problem is that I would like the background of the printed text to be transparent, but SetBkMode does not seem to work (it actually makes no difference if I set it to OPAQUE or TRANSPARENT) so I get a solid background. Any ideas? What am I missing?
edit: Changed LPRECT to RECT, as suggested.
edit: using transparent window:
creating window:
CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED, // extended style
(LPCWSTR)WINDOW_CLASS_NAME, // class
L"test", // title
NULL,
0, 0, // initial x,y
400, 300, // initial width, height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance of this application
NULL)
globals:
wchar_t tst_Str[] = L"TEST";
WM_PAINT:
PAINTSTRUCT ps;
HDC hdc;
RECT rc;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
SetTextColor(hdc, RGB(255, 0, 0));
DrawText(hdc, tst_Str, -1, &rc,NULL);
EndPaint(hwnd, &ps);
return 0;
Windows are responsible for painting themselves. The system is not designed to allow external parties to draw on other windows in the manner you are attempting. You will have to recalibrate your expectations.
If you wish to draw something you should create a window and draw on it. You are at liberty to make the window a transparent layered window and position your drawing so that it appears on top of another window. And you also gain the benefit that you don't need to run a busy loop. You can paint in the standard way, in response to WM_PAINT messages.
To make a layered window appear on the desktop, you have to call SetLayeredWindowAttributes function, for example
SetLayeredWindowAttributes(hWnd,
RGB(255, 255, 255), // The transparent color
128, // Opacity of the window
LWA_ALPHA | LWA_COLORKEY); // Enable both features
This example will make portions of the window with white color completely transparent. Parameter bAlpha specifies the opacity of the window (the pixels not affected with crKey).
Here's a screen shot of such window with Test text floating over browser window with this question:
If you create your window without border, using these window styles: WS_POPUP | WS_SYSMENU, then it will look like on the screen shot. I included WS_SYSMENU to have the standard window menu in the taskbar. To force the taskbar to display a button for popup window, include WS_EX_APPWINDOW extended style.

Capture bitmap of entire software window with winapi

I'm trying to capture several software window and print them to my software. The goal is to be able to view two different software side to side even if they overlap.
void MyWindowFinder::drawTo(HWND hWnd){
MyWindow* currentWindow = anchorWindow;
HDC hdcRendering;
HDC hdcMemRendering;
PAINTSTRUCT ps;
hdcRendering = BeginPaint(hWnd, &ps);
hdcMemRendering = CreateCompatibleDC(hdcRendering);
int widthToRender = 0;
for(int i = 0; i < this->anchorWindow->winID ; i++){
HDC hdcCapture;
HDC hdcMemCapture;
HBITMAP hBitmap;
HGDIOBJ oldCaptureBitmap;
HGDIOBJ oldRenderingBitmap;
RECT clientRect;
GetClientRect(currentWindow->hwnd,&clientRect);
int width = clientRect.right-clientRect.left;
int height = clientRect.bottom-clientRect.top ;
if (!(hdcCapture = GetDC (currentWindow->hwnd))){
return;
}
hdcMemCapture = CreateCompatibleDC(hdcCapture);
hBitmap = CreateCompatibleBitmap(hdcCapture,clientRect.right-clientRect.left,clientRect.bottom-clientRect.top);
oldCaptureBitmap = SelectObject(hdcMemCapture, hBitmap);
BitBlt(hdcMemCapture, 0, 0, width, height, hdcCapture, 0,0, SRCCOPY|CAPTUREBLT);
oldRenderingBitmap = SelectObject(hdcMemRendering, hBitmap);
BitBlt(hdcRendering, widthToRender, 0, width, height, hdcMemCapture, 0, 0, SRCCOPY);
widthToRender+= width;
SelectObject(hdcMemRendering, oldRenderingBitmap);
SelectObject(hdcMemCapture, oldCaptureBitmap);
DeleteDC(hdcMemCapture);
DeleteDC(hdcCapture);
DeleteObject(hBitmap);
currentWindow = currentWindow->previousWindow;
}
DeleteDC(hdcMemRendering);
DeleteDC(hdcRendering);
EndPaint(hWnd, &ps);
}
This works pretty well and I can print two overlapping window side to side in my software :
However I'm facing a tricky problem. When I click on any element of one of my children software, they are not drawn in my software.
Do you have any idea why, and how I could solve this problem ?

win32 - How to draw a rectangle around a text string?

I am new to Win32 and trying to get a GDI based code in C++ ( for technical reasons don't want to use GDI+)
Edit: Simplied the question:
I need to draw a rectangle around the text that is drawn in the middle of the window.
- How can I populate the rectangle co-ordinates?
- Can any one help with the line - Rectangle(x1,y1,x2,y2)? - How to calculate these (x1,y1) & (x2,y2) values?
Thank you..
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rcClient);
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
SetTextColor(hdc, RGB(255, 0, 0));
DrawText(hdc, wstring(s.begin(),s.end()).c_str(), -1, &rectResult, DT_SINGLELINE | DT_CALCRECT);
DrawText(hdc, wstring(s.begin(),s.end()).c_str(), -1, &rcClient, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
// Here I need help - How to I place the rectangle around the Text - which is drawn in the middle of the window?
// It looks like need to use - rectResult.bottom/top/left/right - but don't know how..
Rectangle(hdc, 0,0,100,100);
You don't actually have to center the text yourself. The GDI text output functions can do that for you if you pass the appropriate flags.
For example, if you call DrawText and pass the DT_CENTER flag, it will automatically draw the text in the middle of the specified rectangle (horizontally centered).
Assuming you have only a single line of text (which it sounds like you do), you can get it to automatically vertically center the text by passing the DT_SINGLELINE and DT_VCENTER flags.
So all you really have to do is write code to divide your window's client area up into 4 equal parts, and then pass those rectangles to the DrawText function. That's not terribly difficult. Put a pencil and paper to it if you can't visualize it in your head.
void PaintWindow(HWND hWnd)
{
// Set up the device context for drawing.
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
HPEN hpenOld = static_cast<HPEN>(SelectObject(hDC, GetStockObject(DC_PEN)));
HBRUSH hbrushOld = static_cast<HBRUSH>(SelectObject(hDC, GetStockObject(NULL_BRUSH)));
// Calculate the dimensions of the 4 equal rectangles.
RECT rcWindow;
GetClientRect(hWnd, &rcWindow);
RECT rc1, rc2, rc3, rc4;
rc1 = rc2 = rc3 = rc4 = rcWindow;
rc1.right -= (rcWindow.right - rcWindow.left) / 2;
rc1.bottom -= (rcWindow.bottom - rcWindow.top) / 2;
rc2.left = rc1.right;
rc2.bottom = rc1.bottom;
rc3.top = rc1.bottom;
rc3.right = rc1.right;
rc4.top = rc1.bottom;
rc4.left = rc1.right;
// Optionally, deflate each of the rectangles by an arbitrary amount so that
// they don't butt up right next to each other and we can distinguish them.
InflateRect(&rc1, -5, -5);
InflateRect(&rc2, -5, -5);
InflateRect(&rc3, -5, -5);
InflateRect(&rc4, -5, -5);
// Draw (differently-colored) borders around these rectangles.
SetDCPenColor(hDC, RGB(255, 0, 0)); // red
Rectangle(hDC, rc1.left, rc1.top, rc1.right, rc1.bottom);
SetDCPenColor(hDC, RGB(0, 255, 0)); // green
Rectangle(hDC, rc2.left, rc2.top, rc2.right, rc2.bottom);
SetDCPenColor(hDC, RGB(0, 0, 255)); // blue
Rectangle(hDC, rc3.left, rc3.top, rc3.right, rc3.bottom);
SetDCPenColor(hDC, RGB(255, 128, 0)); // orange
Rectangle(hDC, rc4.left, rc4.top, rc4.right, rc4.bottom);
// Draw the text into the center of each of the rectangles.
SetBkMode(hDC, TRANSPARENT);
SetBkColor(hDC, RGB(0, 0, 0)); // black
// TODO: Optionally, set a nicer font than the default.
DrawText(hDC, TEXT("Hello World!"), -1, &rc1, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
DrawText(hDC, TEXT("Hello World!"), -1, &rc2, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
DrawText(hDC, TEXT("Hello World!"), -1, &rc3, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
DrawText(hDC, TEXT("Hello World!"), -1, &rc4, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
// Clean up after ourselves.
SelectObject(hDC, hpenOld);
SelectObject(hDC, hbrushOld);
EndPaint(hWnd, &ps);
}
RECT rect={0,0,0,0};
const char *str="Test Text";
DrawText(hDC, str, strlen(str), &rect, DT_CALCRECT | DT_NOCLIP);
Rectangle(hDC,rect.left,rect.top,rect.right,rect.bottom);
DrawText(hDC, str, strlen(str), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE|DT_NOCLIP);
Got it finally :) Thanks a lot Cody Gray for pointing me in right direction about this :)
GetTextExtentPoint32(hDC, str, strlen(str), &sz2);
rect2.top=rect2.bottom+sz2.cy;
rect2.right=rect2.top+sz2.cx;
Rectangle(hDC,rect2.left,rect2.top,rect2.right,rect2.bottom);
DrawText(hDC, str, -1, &rect2, DT_CENTER | DT_VCENTER | DT_SINGLELINE|DT_NOCLIP);

Resources