-
May 16th, 2014, 01:39 PM
#121
Re: Capture of Window
Arjay: but the code was working, there was no problem with the callback function. I just added the wrect thing in the main function.
GetWindowRect(hwnd, &wrect);
Code:
if (CODE>82) {
const int fudgey = (rectw.bottom - rectw.top) - dy - 2 * GetSystemMetrics(SM_CYSIZEFRAME);
const int fudgex = 0;
}
This causes error. I don't see any relation between the callback function and this code, except that in callback there is the rectw used too.
One error was unknown identifier rectw and should be wrect used in main. But this does not solve the problem.
Last edited by crazy boy; May 16th, 2014 at 01:59 PM.
-
May 16th, 2014, 01:52 PM
#122
Re: Capture of Window
Code:
const int fudgey = (rectw.bottom - rectw.top) - dy - 2 * GetSystemMetrics(SM_CYSIZEFRAME);
rectw hasn't been defined.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
May 16th, 2014, 01:56 PM
#123
Re: Capture of Window
Originally Posted by crazy boy
Arjay: but the code was working, there was no problem with the callback function. I just added the wrect thing in the main function.
GetWindowRect(hwnd, &wrect);
Code:
if (CODE>82) {
const int fudgey = (rectw.bottom - rectw.top) - dy - 2 * GetSystemMetrics(SM_CYSIZEFRAME);
const int fudgex = 0;
}
This causes error. I don't see any relation between the callback function and this code, except that in callback there is the rectw used too.
Edit
OK solved. I don't know the relation and why this type of error. But the following error was unknown identifier rectw and should be wrect used in main.
callback uses wrect, not rectw!
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
May 16th, 2014, 02:02 PM
#124
Re: Capture of Window
Originally Posted by crazy boy
Why am I getting error?
...
If I remove all from if (CODE>82) till the end except ending curly bracket it succeeds to compile otherwise
'&' : check operator precedence for possible error; use parentheses to clarify precedence
Something with rect, rectw declaration?
Or perhaps, something with "curly bracket"?
Victor Nijegorodov
-
May 16th, 2014, 02:07 PM
#125
Re: Capture of Window
Corrected code 85 on my way (calculation by 2kaud):
Code:
// CODE 81 and 82 de facto no difference
#define CODE 85 // 81
#define WINDOW_MIN_HEIGHT 200
#define WINDOW_MAX_HEIGHT 700
#define WINSTYLE 0x14FF0000
// #define IS_CHILD TRUE // [TRUE | FALSE | 0] ... 0 - deactivates this detection
// GetWindowLong: GWL_HWNDPARENT
#include <windows.h>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <cstring>
#include <string>
#include <tchar.h>
#include <conio.h>
using namespace std;
const int maxstr = 200;
// const char wndtitle[] = "AOK";
LONG t1; LONG t2;
RECT rect, wrect;
int fudgex, fudgey;
struct windata {
static const string titles[]; // only static const integral data members can be initialized within a class
static const string default;
string choose;
HWND hfnd; // Found destination window handler
};
const string windata::titles[] = {"learn", "dialog", "aok", "map" };
const string windata::default = "learn"; // windata.default = ... will produce syntax error : missing ';' before '.'
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam)
{
char title[maxstr + 1];
char *ch = title;
GetWindowRect(hwnd, &wrect); // Calculate window height
int winHeight = wrect.bottom-wrect.top;
if ( (WINDOW_MIN_HEIGHT && winHeight<WINDOW_MIN_HEIGHT) ||
(WINDOW_MAX_HEIGHT && winHeight>WINDOW_MAX_HEIGHT))
return TRUE; // skip window
if ( GetWindowLong(hwnd, GWL_STYLE) & WINSTYLE != TRUE )
return TRUE;
/* GetWindowTextA - copies the text of the specified window's
title bar (if it has one) into a buffer. If the specified window is a
control, the text of the control is copied. However, it
can't retrieve the text of a control in another application. */
if (GetWindowTextA(hwnd, title, maxstr)) {
for (char *ch = title; *ch; ++ch) // was ch++)
*ch = (char)tolower(*ch);
// strstr - finds the first occurrence of a substring within a string. The comparison is case-sensitive.
// c_str - converts the contents of a string as a C-style, null-terminated string.
if (strstr(title, ((windata*)lparam)->choose.c_str())) {
((windata*)lparam)->hfnd = hwnd;
SetLastError(ERROR_NO_MATCH);
cout << "Found matching window - " << title << endl;
return FALSE;
}
}
return TRUE;
} // Press F5 to continue debug, not F10. Otherwise "error" occurs.
int main()
{
// HWND HCapture = GetForegroundWindow();
/* HWND HCapture = FindWindow(NULL, _T("Learning WInAPI")); // get window handle
*/
windata wd;
cout << "Partial window title: ";
getline(cin, wd.choose);
wd.choose.erase(wd.choose.find_last_not_of(" \n\r\t")+1); // trim string
if ( wd.choose == "" ) // select default window
wd.choose = wd.default;
/* EnumWindows(in,in) - Enumerates all top-level windows on the
screen by passing the handle to each window, in turn, to
callback function. EnumWindows continues until the last top-level
window is enumerated or the callback function returns FALSE.
The EnumWindows function does not enumerate child windows.
*/
if (EnumWindows(EnumWindowsProc, (LPARAM)&wd) || (GetLastError() != ERROR_NO_MATCH)) {
cout << "Cannot find window\n";
return 1;
}
HWND HCapture = wd.hfnd;
if (!IsWindow(HCapture)) {
cout << "Bad find! Cannot find window\n";_getch();return 2;
}
#if CODE<85
fudgey = (GetMenu(HCapture)?GetSystemMetrics(SM_CYMENU):0)
+ GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYSIZEFRAME);
fudgex = 0;
#endif
GetClientRect(HCapture, &rect);
LONG dx = rect.right - rect.left;
LONG dy = rect.bottom - rect.top;
if (CODE>82) {
/*
const int fudgey = (GetMenu(HCapture)?GetSystemMetrics(SM_CYMENU):0)
+ GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYSIZEFRAME);
*/
fudgey = (wrect.bottom - wrect.top) - dy - 2 * GetSystemMetrics(SM_CYSIZEFRAME);
fudgex = 0;
}
// create BITMAPINFO structure
// used by CreateDIBSection
BITMAPINFO info = {0};
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biWidth = dx + fudgex;
info.bmiHeader.biHeight = dy + fudgey;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 24;
info.bmiHeader.biCompression = BI_RGB;
HDC HDevice = CreateCompatibleDC(NULL);
//HDC HDevice = GetDC(HCapture);
BYTE* memory = 0;
HBITMAP HBitmap = CreateDIBSection(HDevice, &info, DIB_RGB_COLORS, (void**)&memory, NULL, NULL);
SelectObject(HDevice, HBitmap);
SendMessage(HCapture, WM_PRINTCLIENT, 0, 0);
// SendMessage(HCapture, WM_PRINTCLIENT,(WPARAM) HDevice, 0);
if (!PrintWindow(HCapture, HDevice, /*PW_CLIENTONLY*/0))
return 2;
SendMessage(HCapture, WM_PRINTCLIENT, 0, 0);
ReleaseDC(HCapture, HDevice);
char *buffer = new char[50];
sprintf(buffer, "capture%d%d.bmp", dx, dy);
ofstream file(buffer, ios::binary);
if (!file) {
DeleteObject(HBitmap);
return 1;
}
// initialize bitmap file headers
BITMAPFILEHEADER fileHeader = {0};
BITMAPINFOHEADER infoHeader = {0};
fileHeader.bfType = 0x4d42;
fileHeader.bfSize = 0; //????
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
infoHeader.biSize = sizeof(infoHeader);
infoHeader.biWidth = dx + fudgex;
infoHeader.biHeight = dy;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 24;
infoHeader.biCompression = BI_RGB;
// save file headers
file.write((char*)&fileHeader, sizeof(fileHeader));
file.write((char*)&infoHeader, sizeof(infoHeader));
// save 24-bit bitmap data
int wbytes = (((24 * (dx) + 31) & (~31)) / 8);
int tbytes = wbytes * dy;
file.write((char*)(memory), tbytes);
file.close();
// delete bitmap
DeleteObject(HBitmap);
return 0;
}
Result:
So there are big spaces still
BTW: Can you describe the calculation?
Code:
LONG dy = rect.bottom - rect.top;
fudgey = (wrect.bottom - wrect.top) - dy - 2 * GetSystemMetrics(SM_CYSIZEFRAME);
What is -2? Do you mean border? My border does not look like 2 px.
My window edge has 4 pixels total:
Idk what it is. Maybe doubled border with padding and margin :-)
Last edited by crazy boy; May 16th, 2014 at 02:16 PM.
-
May 16th, 2014, 02:09 PM
#126
Re: Capture of Window
Don't use globals. Look..., in your callback, you need to get the rect of the current window, so just declare a local rect variable and use it inside the callback.
Using a global doesn't save you anything and it only causes grief later (because as the program grows in complexity, it becomes more difficult to find out where the global variable was changed).
An important programming concept to learn is encapsulation along with controlling variable scope.
-
May 16th, 2014, 02:15 PM
#127
Re: Capture of Window
I know, but I thought that is the bug. I wanted to use local here and there but the bug occurred.
I don't know how to solve it if I should not to make the global. The bug "operator precedence" will be there!!!
What is what on the pics bellow:
Theme:
Apply:
The wide area in map window was not captured, but it is up same as in the left
It is same for inactive and active border....
That's all. So I don't know how the style is defined. But looks the border has at least 3 pixels in this case. One px is the highlight or shadow, then there is the gray area which is 1px in my case, in the image above is 15px and there are 1 and 1 pixel between the frames
I still don't know what numbers you operate with. What parts of the images are included in your calculation?
Last edited by crazy boy; May 16th, 2014 at 02:43 PM.
-
May 16th, 2014, 02:41 PM
#128
Re: Capture of Window
Originally Posted by crazy boy
Result:
So there are big spaces still
BTW: Can you describe the calculation?
Code:
LONG dy = rect.bottom - rect.top;
fudgey = (wrect.bottom - wrect.top) - dy - 2 * GetSystemMetrics(SM_CYSIZEFRAME);
What is -2? Do you mean border? My border does not look like 2 px.
My window edge has 4 pixels total:
Idk what it is. Maybe doubled border with padding and margin :-)
This is to do with the 'fudge' factor I talked about in some of my previous posts. PrintWindow() doesn't seem to do what is required or work as documented (see previous posts) so I attempted to manipulate the captured image to only save the client part and not the non-client part which is also returned with PrintWindow(). The fudgex and fudegy values were guesstimates as to what needs to be done to the image from PrintWindow() to only get the client area and as I said previously is a 'kludge' that I don't like and the values are 'try it and see'. The area at the top to remove is basically the difference between the size of the overall window and the size of the client area together with the size of two window borders (top and bottom) [note not 2 px but subtract 2 times frameheight]. This assumes that the window to be captured is a normal overlapped type window. If the window to be captured is of a different type, then you'll need to try different values for fudgex and fudgey until you get the result required. Also as I said previously, you will need to look everywhere dx and dy are used to determine if fudgex and fludgey are needed. Also, if he result is not as required, then again you'll just need to try different values for fudgex and fudgey until you get somewhere near what you want. Yes, as I said before I don't like it but unless any other guru knows how to get PrintWindow() to do what is required I don't know another way using this function.
Incidentally, as it is very obvious that PrintWindow() isn't providing what you want and workarounds are just nasty 'kludges', why persist in using it? Why not use other methods of capturing the client area of a window as per links previously provided?
Last edited by 2kaud; May 16th, 2014 at 02:46 PM.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
May 16th, 2014, 02:53 PM
#129
Re: Capture of Window
Originally Posted by crazy boy
I know, but I thought that is the bug. I wanted to use local here and there but the bug occurred.
I don't know how to solve it if I should not to make the global. The bug "operator precedence" will be there!!!
What you are trying to do is use the result of GetWindowRect() called in the enum function back in the main function when a window has been found. If you want to do this, then put wrect as part of the windata struct. It is considered good programming style/practice to only have const variables (ie ones that don't change) at global scope.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
May 16th, 2014, 03:11 PM
#130
Re: Capture of Window
I still don't understand the concept of "start point" where the capture is calculated from. Does the PrintWindow() take middle of the window as "start point?". Let's have window which has 10px width and 10px height. it has 4 pixels at bottom and 4 pixels at top.
Let's have title area 24 px height. I move the window to coords 14,38. So the Print calculates the "start point" in the middle?
It calculates x=7 because 14/2 for? And y then 14/2+24=31? If the point is in the middle of the window that makes sense to me. Because all we have is width and height:
Code:
info.bmiHeader.biWidth = dx + fudgex;
info.bmiHeader.biHeight = dy + fudgey;
This give us approximate calculation because there can be either even or odd height.
But in the case that they have the beginning point in the top left corner of the window that does not make sense to me at all. Because in that case your data which you calculate could not effect the position of the capture area, only its width and height. So we could always start own capture in same position, but changing position of the right and bottom side of the "cut" area.
Last edited by crazy boy; May 17th, 2014 at 12:48 AM.
-
July 12th, 2015, 08:57 AM
#131
Re: Capture of Window
I have read this answer:
http://stackoverflow.com/questions/4...ow-do-i-get-it
from stukelly.
The problem I wanted to solve was how to obtain the correct area of the Window to capture. I think the answer is in the link. I recalled this topic so I posted it here for the case of later use.
In my case the border.x result is 8px and border width is 4px (x2=8px).
border.y 30 and it is Window Title + border.x ... so 30-8 = Title height.
-
July 12th, 2015, 06:50 PM
#132
Re: Capture of Window
Originally Posted by crazy boy
I have read this answer:
http://stackoverflow.com/questions/4...ow-do-i-get-it
from stukelly.
The problem I wanted to solve was how to obtain the correct area of the Window to capture. I think the answer is in the link. I recalled this topic so I posted it here for the case of later use.
In my case the border.x result is 8px and border width is 4px (x2=8px).
border.y 30 and it is Window Title + border.x ... so 30-8 = Title height.
This is standard stuff that was answered earlier in the thread. Do us both a favor and do what was suggested in one of the other threads - learn the WinAPI basics by working through a copy of Petzold's Windows Programming book.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|