C++ Screenshot on mouse click does not work - c++

I am using Visual Studio 2017, I wrote code which should create a folder, capture a screenshot when the mouse button is pressed and save the screenshot to a .bmp file. But I don't know why that script does not work. Visual Studio compile it without errors / warnings.
Here is the code:
// variable to store the HANDLE to the hook. Don't declare it anywhere else then globally
// or you will get problems since every function uses this variable.
HHOOK _hook;
// This struct contains the data received by the hook callback. As you see in the callback function
// it contains the thing you will need: vkCode = virtual key code.
KBDLLHOOKSTRUCT kbdStruct;
int filenum = 1;
// This is the callback function. Consider it the event that is raised when, in this case,
// a key is pressed.
void TakeScreenShot(const char* filename)
{
//keybd_event(VK_SNAPSHOT, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
//keybd_event(VK_SNAPSHOT, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
HBITMAP h;
POINT a, b;
a.x = 0;
a.y = 0;
b.x = GetSystemMetrics(SM_CXSCREEN);
b.y = GetSystemMetrics(SM_CYSCREEN);
HDC hScreen = GetDC(NULL);
HDC hDC = CreateCompatibleDC(hScreen);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, abs(b.x - a.x), abs(b.y - a.y));
HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
BOOL bRet = BitBlt(hDC, 0, 0, abs(b.x - a.x), abs(b.y - a.y), hScreen, a.x, a.y, SRCCOPY);
// save bitmap to clipboard
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();
// clean up
SelectObject(hDC, old_obj);
DeleteDC(hDC);
ReleaseDC(NULL, hScreen);
DeleteObject(hBitmap);
OpenClipboard(NULL);
h = (HBITMAP)GetClipboardData(CF_BITMAP);
CloseClipboard();
HDC hdc = NULL;
FILE*fp = NULL;
LPVOID pBuf = NULL;
BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;
do
{
hdc = GetDC(NULL);
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
GetDIBits(hdc, h, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS);
if (bmpInfo.bmiHeader.biSizeImage <= 0)
bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount + 7) / 8;
if ((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL)
{
MessageBox(NULL, TEXT("Unable to Allocate Bitmap Memory"), TEXT("Error"), MB_OK | MB_ICONERROR);
break;
}
bmpInfo.bmiHeader.biCompression = BI_RGB;
GetDIBits(hdc, h, 0, bmpInfo.bmiHeader.biHeight, pBuf, &bmpInfo, DIB_RGB_COLORS);
if ((fp = fopen(filename, "wb")) == NULL)
{
MessageBox(NULL, TEXT("Unable to Create Bitmap File"), TEXT("Error"), MB_OK | MB_ICONERROR);
break;
}
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType = 'MB';
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(pBuf, bmpInfo.bmiHeader.biSizeImage, 1, fp);
}
while (false);
if (hdc)ReleaseDC(NULL, hdc);
if (pBuf) free(pBuf);
if (fp)fclose(fp);
}
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
if (wParam == WM_LBUTTONDOWN)
{
std::string OutputFolder = "C:\\temp";
std::string filename = "ss";
if (CreateDirectory(OutputFolder.c_str(), NULL) ||
ERROR_ALREADY_EXISTS == GetLastError())
{
}
else
{
// Failed to create directory.
}
auto numfile = std::to_string(filenum);
TakeScreenShot((OutputFolder + "\\" + filename + std::to_string(filenum) + ".bmp").c_str());
filenum++;
}
}
// call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void ReleaseHook()
{
UnhookWindowsHookEx(_hook);
}
int main()
{
// Don't mind this, it is a meaningless loop to keep a console application running.
// I used this to test the keyboard hook functionality. If you want to test it, keep it in ;)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
}
}
If click with it does not make the directory (if it does not exist) and does not create the .bmp file.

As others have said, you never install your hook! Also, it appears from my tests that you need to be dispatching messages to a window of some sort in order for a WH_MOUSE hook to get called.
Here's a minimal version of main () that works for me:
int main()
{
_hook = SetWindowsHookEx (WH_MOUSE, HookCallback, NULL, GetCurrentThreadId ());
if (_hook == NULL)
...
MessageBox (NULL, "Click OK to quit", "Screen Grabber", MB_OK);
UnhookWindowsHookEx (_hook);
}
Then the rest of your code works fine, albeit is a little bit messy as others have said.
However, this will only catch mouse-clicks within the message box itself, and I don't think that's what you want.
If you want to catch these globally, you will need to install a "low level" mouse hook. This needs to be a global hook but otherwise the code looks much the same. The code to install and run the hook is:
int main()
{
_hook = SetWindowsHookEx (WH_MOUSE_LL, HookCallback, NULL, 0);
MSG msg;
while (GetMessage (&msg, NULL, 0, 0))
DispatchMessage (&msg);
UnhookWindowsHookEx(_hook);
}

Related

ATL: OnDrawThumbnail hDrawDC seems to be monochrome in IThumbnailProvider

I'm working on a C++ ATL COM thumbnail/preview/search project, but its bitmap displaying code behavior is monochrome during the Thumbnail process instead of the colored. The Preview process is colored as expected, using the same function.
I used the ATL Wizard to create the IThumbnailProvider and his friends. My small changes are: I replaced the color from black to pink in the document::OnDrawThumbnail and I wrote the document::OnDrawThumbnail into CPreviewCtrl::DoPaint. I've read the "new DC always monochrome" thing in the MS spec but I could not get colored DC even if a changed the original ATL code OnDrawThumbnail(GetDC(NULL), &rcBounds);. The CreateCompatibleDC(NULL) and CreateCompatibleDC(hDrawDC) were dead-end too.
document.cpp (changed)
// Almost the default sample code, but hDrawBrush is changed to pink
void document::OnDrawThumbnail(HDC hDrawDC, LPRECT lprcBounds)
{
HBRUSH hDrawBrush = CreateSolidBrush(RGB(255, 0, 255)); // pink
FillRect(hDrawDC, lprcBounds, hDrawBrush);
HFONT hStockFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
LOGFONT lf;
GetObject(hStockFont, sizeof(LOGFONT), &lf);
lf.lfHeight = 34;
HFONT hDrawFont = CreateFontIndirect(&lf);
HFONT hOldFont = (HFONT) SelectObject(hDrawDC, hDrawFont);
CString strText = _T("TODO: implement thumbnail drawing here");
DrawText(hDrawDC, strText, strText.GetLength(), lprcBounds, DT_CENTER | DT_WORDBREAK);
SelectObject(hDrawDC, hDrawFont);
SelectObject(hDrawDC, hOldFont);
DeleteObject(hDrawBrush);
DeleteObject(hDrawFont);
}
PreviewHandler.h (changed, it is called by the Preview)
// CPreviewCtrl implementation
class CPreviewCtrl : public CAtlPreviewCtrlImpl
{
protected:
virtual void DoPaint(HDC hdc)
{
// you can obtain a pointer to IDocument as follows
// CMyDoc* pDoc = (CMyDoc*)m_pDocument;
/*
CString strData = _T("Draw Rich Preview content here.");
TextOut(hdc, 10, 20, strData, strData.GetLength());
*/
RECT rc{};
rc.right = 290;
rc.bottom = 290;
dynamic_cast<document*>(m_pDocument)->OnDrawThumbnail(hdc, &rc);
}
};
atlhandlerimpl.h (unchanged, from VS SDK \atlmfc\include\ which is called be the thumbnail provider)
ATLPREFAST_SUPPRESS(6101)
_Success_(return != FALSE) BOOL GetThumbnail(
_In_ UINT cx,
_Out_ HBITMAP* phbmp,
_Out_ WTS_ALPHATYPE* /* pdwAlpha */)
{
HDC hdc = ::GetDC(NULL);
RECT rcBounds;
SetRect(&rcBounds, 0, 0, cx, cx);
HDC hDrawDC = CreateCompatibleDC(hdc);
if (hDrawDC == NULL)
{
ReleaseDC(NULL, hdc);
return FALSE;
}
HBITMAP hBmp = CreateCompatibleBitmap(hDrawDC, cx, cx);
if (hBmp == NULL)
{
ReleaseDC(NULL, hdc);
DeleteDC(hDrawDC);
return FALSE;
}
HBITMAP hOldBitmap = (HBITMAP) SelectObject(hDrawDC, hBmp);
// Here you need to draw the document's data
OnDrawThumbnail(hDrawDC, &rcBounds);
SelectObject(hDrawDC, hOldBitmap);
DeleteDC(hDrawDC);
ReleaseDC(NULL, hdc);
*phbmp = hBmp;
return TRUE;
}
ATLPREFAST_UNSUPPRESS()
Sample thumbnail in the File Explorer
Github helped me. It is definitely an ATL SDK bug.
BUG report on the VS developer community
Solution on the www.patthoyts.tk
And the github repo which helped me: abhimanyusirohi/ThumbFish
In the atlhandlerimpl.h provided GetThumbnail must be override:
BOOL document::GetThumbnail(
_In_ UINT cx,
_Out_ HBITMAP * phbmp,
_Out_ WTS_ALPHATYPE* /* pdwAlpha */)
{
BOOL br = FALSE;
HDC hdc = ::GetDC(NULL);
HDC hDrawDC = CreateCompatibleDC(hdc);
if (hDrawDC != NULL)
{
void* bits = 0;
RECT rcBounds;
SetRect(&rcBounds, 0, 0, cx, cx);
BITMAPINFO bi = { 0 };
bi.bmiHeader.biWidth = cx;
bi.bmiHeader.biHeight = cx;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biSizeImage = 0;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
HBITMAP hBmp = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, &bits, NULL, 0);
if (hBmp != NULL)
{
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hDrawDC, hBmp);
OnDrawThumbnail(hDrawDC, &rcBounds);
SelectObject(hDrawDC, hOldBitmap);
*phbmp = hBmp;
br = TRUE;
}
DeleteDC(hDrawDC);
}
ReleaseDC(NULL, hdc);
return br;
}

Capture screenshot of minimized window [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I tried to follow the example found:
Capturing an image from a minimized window
My code:
#include <iostream>
#include <string>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
#pragma warning(disable : 4996)
using namespace std;
using namespace Gdiplus;
int GetEncoderClsid(LPCWSTR format, CLSID* pClsid)
{
unsigned int num = 0, size = 0;
GetImageEncodersSize(&num, &size);
if (size == 0) return -1;
ImageCodecInfo* pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL) return -1;
GetImageEncoders(num, size, pImageCodecInfo);
for (unsigned int j = 0; j < num; ++j) {
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}
int SaveScreenshot(string filename, ULONG uQuality, HWND hwnd) // by Napalm
{
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HWND hMyWnd = hwnd;
//HWND hMyWnd = GetDesktopWindow();
RECT r;
int w, h;
HDC dc, hdcCapture;
int nBPP, nCapture, iRes;
LPBYTE lpCapture;
CLSID imageCLSID;
Bitmap* pScreenShot;
// get the area of my application's window
GetWindowRect(hMyWnd, &r);
dc = GetWindowDC(hMyWnd); // GetDC(hMyWnd) ;
w = r.right - r.left;
h = r.bottom - r.top;
nBPP = GetDeviceCaps(dc, BITSPIXEL);
hdcCapture = CreateCompatibleDC(dc);
// create the buffer for the screenshot
BITMAPINFO bmiCapture = { sizeof(BITMAPINFOHEADER), w, -h, 1, nBPP, BI_RGB, 0, 0, 0, 0, 0, };
// create a container and take the screenshot
HBITMAP hbmCapture = CreateDIBSection(dc, &bmiCapture, DIB_PAL_COLORS, (LPVOID*)&lpCapture, NULL, 0);
// failed to take it
if (!hbmCapture) {
DeleteDC(hdcCapture);
DeleteDC(dc);
GdiplusShutdown(gdiplusToken);
printf("failed to take the screenshot. err: %d\n", GetLastError());
return 0;
}
// copy the screenshot buffer
nCapture = SaveDC(hdcCapture);
SelectObject(hdcCapture, hbmCapture);
BitBlt(hdcCapture, 0, 0, w, h, dc, 0, 0, SRCCOPY);
RestoreDC(hdcCapture, nCapture);
DeleteDC(hdcCapture);
DeleteDC(dc);
// save the buffer to a file
pScreenShot = new Bitmap(hbmCapture, (HPALETTE)NULL);
EncoderParameters encoderParams;
encoderParams.Count = 1;
encoderParams.Parameter[0].NumberOfValues = 1;
encoderParams.Parameter[0].Guid = EncoderQuality;
encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParams.Parameter[0].Value = &uQuality;
GetEncoderClsid(L"image/jpeg", &imageCLSID);
wchar_t* lpszFilename = new wchar_t[filename.length() + 1];
mbstowcs(lpszFilename, filename.c_str(), filename.length() + 1);
iRes = (pScreenShot->Save(lpszFilename, &imageCLSID, &encoderParams) == Ok);
delete pScreenShot;
DeleteObject(hbmCapture);
GdiplusShutdown(gdiplusToken);
return iRes;
}
int main() {
HWND hWnd;
hWnd = FindWindowA(NULL, "txt.txt - Bloco de Notas");
WINDOWPLACEMENT wp = { 0 };
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hWnd, &wp);
ANIMATIONINFO ai = { 0 };
bool restoreAnimated = false;
if (wp.showCmd == SW_SHOWMINIMIZED)
{
ai.cbSize = sizeof(ANIMATIONINFO);
SystemParametersInfo(SPI_GETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
if (ai.iMinAnimate != 0)
{
ai.iMinAnimate = 0;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
restoreAnimated = true;
}
// optionally move the window off-screen, or
// apply alpha using SetLayeredWindowAttributes()...
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
}
// capture as needed ...
string path = "C:\\Users\\CAIO\\Desktop\\screenshot.jpg";
ULONG quality = 100;
SaveScreenshot(path, quality, hWnd);
if (wp.showCmd == SW_SHOWMINIMIZED)
{
SetWindowPlacement(hWnd, &wp);
// optionally remove alpha using SetLayeredWindowAttributes()...
if (restoreAnimated)
{
ai.iMinAnimate = 1;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
}
}
return 0;
}
In her code there's restoreAnimation = true; and if (restoreAnimation) did he mean restoreAnimated?
With the code above it still shown the window for a sec, also the captured image is all black (maybe captured while minimized) or is not captured properly.
https://youtu.be/8b1wXxtaXsY?t=9
Sec 8 and 9 from the video you can see the window is being shown on the screen.
Suggestions?
did he mean restoreAnimated?
I think yes.
This code from #Remy only disables the animation effects when minimizing and restoring, the window will still be displayed for a short time when restoring. As the answer pointed out, you can use SetLayeredWindowAttributes to make the window nearly completely transparent(It should be noted that using SetLayeredWindowAttributes needs to ensure that hwnd has WS_EX_LAYERED style.) and then you will not see the window, but the operating system will.
In addition, the problem of incomplete window capture is because the window is not drawn completely, call UpdateWindow after ShowWindow works for me, it will send a WM_PAINT message to the window.
bool restoreAnimated = false;
BYTE Alph = 0;
LONG_PTR exstyle = 0;
if (wp.showCmd == SW_SHOWMINIMIZED)
{
ai.cbSize = sizeof(ANIMATIONINFO);
SystemParametersInfo(SPI_GETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
if (ai.iMinAnimate != 0)
{
ai.iMinAnimate = 0;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
restoreAnimated = true;
}
// optionally move the window off-screen, or
// apply alpha using SetLayeredWindowAttributes()...
exstyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exstyle | WS_EX_LAYERED);
DWORD flag;
BOOL ret = GetLayeredWindowAttributes(hWnd, 0, &Alph, 0);
SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
UpdateWindow(hWnd);
}
// capture as needed ...
string path = "C:\\Users\\name\\Desktop\\screenshot.jpg";
ULONG quality = 100;
SaveScreenshot(path, quality, hWnd);
if (wp.showCmd == SW_SHOWMINIMIZED)
{
SetWindowPlacement(hWnd, &wp);
// optionally remove alpha using SetLayeredWindowAttributes()...
SetLayeredWindowAttributes(hWnd, 0, Alph, LWA_ALPHA);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exstyle);
if (restoreAnimated)
{
ai.iMinAnimate = 1;
SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
}
}

Write CreateDIBSection BMP Data to File

I have taken a screenshot programtically and I want to write out the BGRA to file. The BGRA is held in pixelBuffer.
Here is the code I am using to write to file:
BYTE *pixelBuffer;
HBITMAP hbmp;
hbmp = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, (void **)&pixelBuffer, NULL, 0);
FILE *stream;\
if (fopen_s(&stream, "C:\\Users\Vayeate\\Desktop\\blah.txt", "wb+") == 0) {
fwrite(pixelBuffer, (screenHeight * screenWidth * 4), (size_t)(sizeof(CHAR) + 1), stream); // (screenWidth * screenHeight * 4)
fclose(stream);
}
However this writes a bunch of gibberish that looks like:
òîîÿòîîÿ
And that repeat forever. I was hoping to get something like 255, 100, 100, 255.
Here is my full code:
#include <Windows.h>
#include <stdio.h>
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int)
{
//Sleep(1000)
MessageBox(0, L"Hello World", L"Unipen", MB_ICONINFORMATION);
int i = 0;
DISPLAY_DEVICE device;
device.cb = sizeof(device);
while (EnumDisplayDevices(NULL, i, &device, 0) && ++i) {
if ((device.StateFlags & DISPLAY_DEVICE_ACTIVE) != DISPLAY_DEVICE_ACTIVE) {
MessageBox(0, device.DeviceName, L"CONTINUE", MB_ICONINFORMATION);
continue;
}
MessageBox(0, device.DeviceName, L"BREAK", MB_ICONINFORMATION);
break;
}
size_t screenWidth = 1920;
size_t screenHeight = 1200;
size_t colorLen = 4;
HDC hdcScreen;
hdcScreen = CreateDC(NULL, device.DeviceName, NULL, NULL);
if (hdcScreen == (HDC)NULL) {
MessageBox(0, L"UnableToCreateDC", L"ERROR", MB_ICONINFORMATION);
return 0;
}
HDC hdcMemoryDC;
hdcMemoryDC = CreateCompatibleDC(hdcScreen);
if (hdcMemoryDC == (HDC)NULL) {
DeleteDC(hdcScreen);
MessageBox(0, L"UnableToCreateCompatibleDC", L"ERROR", MB_ICONINFORMATION);
return 0;
}
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (LONG)screenWidth;
bmi.bmiHeader.biHeight = (-1)*(LONG)screenHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
BYTE *pixelBuffer;
HBITMAP hbmp;
hbmp = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, (void **)&pixelBuffer, NULL, 0);
if (hbmp == (HBITMAP)NULL) {
DeleteDC(hdcScreen);
DeleteDC(hdcMemoryDC);
MessageBox(0, L"UnableToCreateDIBSection", L"ERROR", MB_ICONINFORMATION);
return 0;
}
//HGDIOBJ rez_selected;
HBITMAP rez_selected_bmp;
rez_selected_bmp = (HBITMAP)SelectObject(hdcMemoryDC, hbmp);
if (rez_selected_bmp == (HBITMAP)NULL) {
DeleteDC(hdcScreen);
DeleteDC(hdcMemoryDC);
DeleteObject(hbmp);
MessageBox(0, L"UnableToCreateDIBSection", L"ERROR", MB_ICONINFORMATION);
return 0;
}
BitBlt(hdcMemoryDC, 0, 0, screenWidth, screenHeight, hdcScreen, 0, 0, SRCCOPY);
//(void) SelectObject(hdcMemoryDC, rez_selected_bmp); // i dont do this step in nativeshot
FILE *stream;\
if (fopen_s(&stream, "C:\\Users\Vayeate\\Desktop\\blah.txt", "wb+") == 0) {
fwrite("asdfasdfasdf", 1, (size_t)(sizeof(CHAR) + 1), stream); // (screenWidth * screenHeight * 4)
fclose(stream);
}
DeleteDC(hdcScreen);
DeleteDC(hdcMemoryDC);
DeleteObject(hbmp);
MessageBox(0, L"DONE", L"Unipen", MB_ICONINFORMATION);
return 0;
}
How can I get space delimited BGRA data to file?
You're writing binary data and reading it as text. Thus, òîîÿòîîÿ is incidentally probably the correct output, as these are the characters that the binary values map to, according to the character map used by the text editor that displayed it.
If you want to have space-delimited values of the pixels in the buffer as "human-readable" ASCII written into a text file, you'll first have to use fprintf to convert these values accordingly.
Use this as an example :
if (fopen_s(&stream, "C:\\Users\Vayeate\\Desktop\\blah.txt", "w") == 0) {
for(size_t px = 0 ; px < (screenHeight * screenWidth * 4) ; ++px) {
fprintf(stream, "%hhu, ", pixelBuffer[px]);
}
fclose(stream);
}

Locating program positions on screen

If I open notepad.exe from a C++ program using CreateProcess(), is it possible to find the location of that notepad window which has started? I want to find its X and Y positions on screen.
Code: (Improved by suggestions) // Works
Procces = CreateProcess(
"C:\\Windows\\System32\\notepad.exe",
"-l D:\\Testing.txt",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi);
WaitForSingleObject(pi.hProcess, 1000);
HWND hwndNotePad = FindWindow(NULL, "Testing.txt - Notepad");
RECT r;
if (INVALID_HANDLE_VALUE != hwndNotePad) {
GetWindowRect(hwndNotePad, &r);
cout << r.bottom << endl;
}
Something like this:
HWND hwndNotePad = FindWindow(NULL, "Untitled - Notepad");
RECT r;
if (NULL != hwndNotePad) {
GetWindowRect(hwndNotePad, &r);
}
If you don't know the exact name, you can use EnumWindows. This is off the top of my head, so there might be errors:
main()
{
//// .....
HWND hwndNotePad = NULL; // Store the result here
EnumWindows(enumProc, (LPARAM)(&hwndNotePad); // Check all windows
if (NULL != hwndNotePad) {
// Window found
RECT r;
GetWindowRect(hwndNotePad, &r);
}
//// ......
}
BOOL CALLBACK enumProc(HWND hwnd, LPARAM lParam)
{
// Get title bar text
char winTitle[256];
GetWindowText(hwnd, winTitle, 256);
if (NULL != strstr(winTitle, "Notepad")) { // Check for match
HWND *match = (HWND *)lParam;
*match = hwnd; // Save result
return FALSE; // No need to keep checking
}
else {
return TRUE; // No match. Keep checking
}
}

Double buffering for my Menu

i have implemented double buffering in my application, using the code below.
After wards, i found that my child windows (ie, buttoms), was not animating like normal, so i added WS_EX_COMPOSITED to my parent window, and the child windows are now animating correctly. However, after adding WS_EX_COMPOSITED, my Menu that is created from my resource, is black, and not displaying properly.
So, how to add double buffering to my top Menu?
MainWinHwnd = CreateWindowEx(WS_EX_COMPOSITED, MainWinClassName, MainWinTitle,
WS_VISIBLE|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SIZEBOX|WS_CLIPCHILDREN,
NULL, NULL, 609, 440, NULL, NULL, hInstance, NULL);
if (!MainWinHwnd) return FALSE;
case WM_PAINT:
{
RECT WinRt;
RECT TxtRt;
HFONT TxtFont = NULL;
SIZE TxtSize;
HDC WinDC = GetDC(hWnd);
GetClientRect(hWnd, &WinRt);
HDC WinBuffer = CreateCompatibleDC(WinDC);
HBITMAP BitBuffer = CreateCompatibleBitmap(WinDC, WinRt.right, WinRt.bottom);
SelectObject(WinBuffer, BitBuffer);
FillRect(WinBuffer, &WinRt, (HBRUSH) (COLOR_BTNFACE + 1));
SetBkColor(WinBuffer, GetSysColor((COLOR_BTNFACE)));
DrawThemeBackground(ButtonThemeData, WinBuffer, BP_GROUPBOX, GBS_NORMAL, &GroupOptionBox, NULL);
DrawThemeBackground(DragDropThemeData, WinBuffer, RP_GRIPPER, 0, &DragDropItem, NULL);
for (DWORD I = 0; I < sizeof(MainWinLabels) / sizeof(CustomLabel); I++)
{
if (MainWinLabels[I].Font == NULL)
{
TxtFont = CreateFontA(MainWinLabels[I].cFontHeight, NULL, NULL, NULL, FW_DONTCARE,
MainWinLabels[I].cFontItalic, MainWinLabels[I].cFontUnderline,
MainWinLabels[I].cFontStrikeOut, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
MainWinLabels[I].cFontQuality, DEFAULT_PITCH, MainWinLabels[I].cFontFaceName);
if (TxtFont == NULL) continue;
SelectObject(WinBuffer, TxtFont);
}
else SelectObject(WinBuffer, *MainWinLabels[I].Font);
SetTextColor(WinBuffer, MainWinLabels[I].Color);
TxtRt.left = MainWinLabels[I].X;
TxtRt.top = MainWinLabels[I].Y;
DrawTextA(WinBuffer, MainWinLabels[I].Text, strlen(MainWinLabels[I].Text), &TxtRt,
DT_LEFT|DT_SINGLELINE|DT_NOCLIP);
GetTextExtentPoint32A(WinBuffer, MainWinLabels[I].Text, strlen(MainWinLabels[I].Text), &TxtSize);
MainWinLabels[I].Width = TxtSize.cx;
MainWinLabels[I].Height = TxtSize.cy;
if (TxtFont != NULL) DeleteObject(TxtFont);
}
BitBlt(WinDC, 0, 0, WinRt.right, WinRt.bottom, WinBuffer, 0, 0, SRCCOPY);
ReleaseDC(hWnd, WinDC);
DeleteObject(BitBuffer);
DeleteDC(WinBuffer);
break;
}
The solution:
Do not use WS_EX_COMPOSITED.
Instead of using GetDC(hWnd) use BeginPaint(hwnd, &ps) and EndPaint(hwnd, &ps)