PrintWindow: screenshot is offset sometimes - winapi

I'm taking screenshots of windows using PrintWindow(). This works finde with the following code.
This works most of the time - I'm calling it very often in a continuos loop - but sometimes it fails. I started saving screenshots of the times it fails. Sometimes they are just black, but sometimes the ClientArea of the captured window is somehow offset and only visible on half the picture. Why is that the case?
EDIT:
Is the PrintWindow function guaranteed to work, even when its called ~100times a second? What makes me wonder is, that after every print window I'm actually verifying two pixels which default colors I stored as a COLORREF at startup. The program says they match almost all the time. Still, once I use GetPixel, the returned value from other pixels is simply black or white from time to time (which should never be the case). Once I save the HDC/HBITMAP as a screenshot (I called GdiFlush before), the screenshot is just plain black (which shouldn't be the case either, as I said, I checked two pixels before...).
Well for now, back to the initial question: Is this definitely my fault, or is it possible that PrintWindow just gives random results from time to time, without returning an error?
Ok, this is the NEW CODE:
/* Try printing the window 10times, in case it fails. */
for (int i = 0; i <= NUM_ITERATIONS_PREP; i++) {
releaseSurface();
prepared_HWND = hwnd;
window_dc = GetWindowDC(hwnd);
surface = CreateCompatibleDC(window_dc);
if (surface) {
RECT r;
GetWindowRect(hwnd, &r);
bmp = CreateCompatibleBitmap(window_dc, r.right - r.left, r.bottom - r.top);
if (!ReleaseDC(hwnd, window_dc)) {
writeLog("ReleaseDC failed.", black, true);
}
if (bmp) {
old_surface_bmp = SelectBitmap(surface, bmp);
//InvalidateRect(hwnd, 0, TRUE);
//UpdateWindow(hwnd);
int result = PrintWindow(hwnd, surface, 0);
if (result != 0) {
if (!verify || verifySurface())
break;
else {
writeLog("Surface could not be verified on iteration " + std::to_string(i) + ". Saving screenshot.", black, true);
saveDebugScreenshot();
QThread::msleep(2);
}
} else {
writeLog("PrintWindow() failed.", black, true);
}
}
else {
writeLog("BMP creation failed.", black, true);
}
}
else {
writeLog("HDC creation failed.", black, true);
}
}
And the new RELEASE CODE:
/* If you call prepareSurface(), call this once the surface isn't need anymore. */
void ClientProfile::releaseSurface() {
SelectObject(surface, old_surface_bmp);
DeleteDC(surface);
DeleteObject(bmp);
prepared_HWND = NULL;
}
releaseSurface() is called either at the beginning of prepareSurface() and additionally every time I'm done processing a table (this means its called once too often for every prepareSurface(). Is that a problem?).
Oh and old_surface_bmp, bmp and surface are declared as private class attributes.

Related

Custom trackbar ticks

I'm using the stock Trackbar control. I would like to custom draw the ticks.
Here I made an experiment, just trying to draw in the right place:
case WM_NOTIFY:
{
NMHDR* nMhdr = (NMHDR*) lParam;
NMCUSTOMDRAW* nMcd = (NMCUSTOMDRAW*) lParam;
if (nMhdr->code == NM_CUSTOMDRAW)
{
switch (nMcd->dwDrawStage)
{
case CDDS_PREPAINT:
{
return CDRF_NOTIFYITEMDRAW;
}
case CDDS_ITEMPREPAINT:
{
if (nMcd->dwItemSpec == TBCD_TICS)
{
FillRect(nMcd->hdc, &nMcd->rc, (HBRUSH) GetStockObject(BLACK_BRUSH));
return CDRF_SKIPDEFAULT;
}
else
{
return CDRF_DODEFAULT;
}
break;
}
default:
{
result = CDRF_DODEFAULT;
break;
}
}
}
break;
}
In my CDDS_ITEMPREPAINT, if dwItemSpec == TBCD_TICS, then the update rect (NMCUSTOMDRAW->rc) is always an empty rect. I checked, and for the other items (TBCD_CHANNEL and TBCD_THUMB), I get a valid rect and can draw in place of the channel and thumb.
Ok: so what's the point of TBCD_TICS if it doesn't give me a rect to draw in?
So maybe I can get the tick positions another way. Well, there's TBM_GETTICPOS, which seems like it would work. Except the documentation mentions this:
The positions of the first and last tick marks are not directly available via this message.
So how can I get the first and last tick positions? They do not correspond with the start and end of the channel, the ticks are inset slightly. Perhaps we can calculate the insert from the sides of the channel, but that seems fragile (especially on differently scaled displays).
So how can I get the first and last tick positions?
The old method (XP and older) to get them seems to still work (I just tested on Windows 10) :
RECT rectTrackbar;
GetClientRect(hWndTB, &rectTrackbar);
RECT rectThumb;
SendMessage(hWndTB, TBM_GETTHUMBRECT, 0, (LPARAM)&rectThumb);
int nThumbWidth = rectThumb.right - rectThumb.left;
int nXTicFirst = rectTrackbar.left += (nThumbWidth + 2);
int nXTicLast = rectTrackbar.right -= (nThumbWidth + 2 + 1);

Cannot get OpenAL to play sound

I've searched the net, I've searched here. I've found code that I could compile and it works fine, but for some reason my code won't produce any sound. I'm porting an old game to the PC (Windows,) and I'm trying to make it as authentic as possible, so I'm wanting to use generated wave forms. I've pretty much copied and pasted the working code (only adding in multiple voices,) and it still won't work (even thought the exact same code for a single voice works fine.) I know I'm missing something obvious, but I just cannot figure out what. Any help would be appreciated thank you.
First some notes... I was looking for something that would allow me to use the original methodology. The original system used paired bytes for music (sound effects - only 2 - were handled in code.) A time byte that counted down every time the routine was called, and a note byte that was played until time reached zero. this was done by patching into the interrupt vector, windows doesn't allow that, so I set up a timer that routing that accomplished the same thing. The timer kicks in, updates the display, and then runs the music sequence. I set this up with a defined time so that I only have one place to adjust the timing at (to get it as close as possible to the original sequence. The music is a generated wave form (and I've double checked the math, and even examined the generated data in debug mode,) and it looks good. The sequence looks good, but doesn't actually produce sound. I tried SDL2 first, and it's method of only playing 1 sound doesn't work for me, also, unless I make the sample duration extremely short (and the sound produced this way is awful,) I can't match the timing (it plays the entire sample through it's own interrupt without letting me make adjustments.) Also, blending the 3 voices together (when they all run with different timings,) is a mess. Most of the other engines I examined work in much the same way, they want to use their own callback interrupt and won't allow me to tweak it appropriately. This is why I started working with OpenAL. It allows multiple voices (sources,) and allows me to set the timings myself. On advice from several forums, I set it up so that the sample lengths are all multiples of full cycles.
Anyway, here's the code.
int main(int argc, char* argv[])
{
FreeConsole(); //Get rid of the DOS console, don't need it
if (InitLog() < 0) return -1; //Start logging
UINT_PTR tim = NULL;
SDL_Event event;
InitVideo(false); //Set to window for now, will put options in later
curmusic = 5;
InitAudio();
SetTimer(NULL,tim,_FREQ_,TimerProc);
SDL_PollEvent(&event);
while (event.type != SDL_KEYDOWN) SDL_PollEvent(&event);
SDL_Quit();
return 0;
}
void CALLBACK TimerProc(HWND hWind, UINT Msg, UINT_PTR idEvent, DWORD dwTime)
{
RenderOutput();
PlayMusic();
//UpdateTimer();
//RotateGate();
return;
}
void InitAudio(void)
{
ALCdevice *dev;
ALCcontext *cxt;
Log("Initializing OpenAL Audio\r\n");
dev = alcOpenDevice(NULL);
if (!dev) {
Log("Failed to open an audio device\r\n");
exit(-1);
}
cxt = alcCreateContext(dev, NULL);
alcMakeContextCurrent(cxt);
if(!cxt) {
Log("Failed to create audio context\r\n");
exit(-1);
}
alGenBuffers(4,Buffer);
if (alGetError() != AL_NO_ERROR) {
Log("Error during buffer creation\r\n");
exit(-1);
}
alGenSources(4, Source);
if (alGetError() != AL_NO_ERROR) {
Log("Error during source creation\r\n");
exit(-1);
}
return;
}
void PlayMusic()
{
static int oldsong, ofset, mtime[4];
double freq;
ALuint srate = 44100;
ALuint voice, i, note, len, hold;
short buf[4][_BUFFSIZE_];
bool test[4] = {false, false, false, false};
if (curmusic != oldsong) {
oldsong = (int)curmusic;
if (curmusic > 0)
ofset = moffset[(curmusic - 1)];
for (voice = 1; voice < 4; voice++)
alSourceStop(Source[voice]);
mtime[voice] = 0;
return;
}
if (curmusic == 0) return;
//Only 3 voices for music, but have
for (voice = 0; voice < 3; voice ++) { // 4 set asside for eventual sound effects
if (mtime[voice] == 0) { //is note finished
alSourceStop(Source[voice]); //It is, so stop the channel (source)
mtime[voice] = music[ofset++]; //Get the next duration
if (mtime[voice] == 0) {oldsong = 0; return;} //zero marks end, so restart
note = music[ofset++]; //Get the next note
if (note > 127) { //Old HW data was designed for could only
if (note == 255) note = 127; //use values 128 - 255 (255 = 127)
freq = (15980 / (voice + (int)(voice / 3))) / (256 - note); //freq of note
len = (ALuint)(srate / freq); //A single cycle of that freq.
hold = len;
while (len < (srate / (1000 / _FREQ_))) len += hold; //Multiply till 1 interrup cycle
while (len > _BUFFSIZE_) len -= hold; //Don't overload buffer
if (len == 0) len = _BUFFSIZE_; //Just to be safe
for (i = 0; i < len; i++) //calculate sine wave and put in buffer
buf[voice][i] = (short)((32760 * sin((2 * M_PI * i * freq) / srate)));
alBufferData(Buffer[voice], AL_FORMAT_MONO16, buf[voice], len, srate);
alSourcei(openAL.Source[i], AL_LOOPING, AL_TRUE);
alSourcei(Source[i], AL_BUFFER, Buffer[i]);
alSourcePlay(Source[voice]);
}
} else --mtime[voice];
}
}
Well, it turns out there were 3 problems with my code. First, you have to link the built wave buffer to the AL generated buffer "before" you link the buffer to the source:
alBufferData(buffer,AL_FORMAT_MONO16,&wave_sample,sample_lenght * sizeof(short),frequency);
alSourcei(source,AL_BUFFER,buffer);
Also in the above example, I multiplied the sample_length by how many bytes are in each sample (in this case "sizeof(short)".
The final problem was that you need to un-link a buffer from the source before you change the buffer data
alSourcei(source,AL_BUFFER,NULL);
The music would play, but not correctly until I added that line to the note change code.

Joystick won't work using SDL

I'm building a simple game in SDL. I've been through countless tutorials and I've clearly missed something as it still ignoring my Joystick completely
In my constructor
SDL_JoystickEventState(SDL_ENABLE);
joystick = SDL_JoystickOpen(0);
In my update I'm calling a test to check I have actually initialized the joystick
if (SDL_NumJoysticks() <= 0)
{
done = true;
}
Here is my player update as well
void World::playerMovement()
{
SDL_Event event;
while (SDL_PollEvent (&event))
{
switch (event.type)
{
case SDL_QUIT:
done = true;
break;
case SDL_JOYAXISMOTION:
if ( ( event.jaxis.value < -3200 ) || (event.jaxis.value > 3200 ) )
{
test = true;
}
break;
}
}
}
Test is simply a bool which once true will mean my enemies start spawning. I also run a check in main
if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0)
{
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
done = true;
}
When I run the game it loads as normal but no matter how much I move the joystick it won't set test to true.
I also tried using the following in the while poll event loop instead.
if (event.type == SDL_JOYAXISMOTION)
{
if(SDL_JoystickGetAxis(joystick, 1) > 0)
{
test = true;
}
}
Any idea's what I have missed?
I think emartel has the best answer to make sure SDL_joystick is working.
When does World::playerMovement() happen? The overall flow of your program is hard to determine from these snippets.
I'm happy to share with you my code for handling joysticks, which keeps track of: multiple joysticks, axes scaled [-1,1] with deadzone removed, and buttons held down.
http://www.raptor007.com/code/RaptorEngine_Joystick.zip
And here's a snippet of how that would be utilized as part of your main loop:
// FIXME: SDL needs to be initialized before we get here.
JoystickManager Joy;
Joy.Initialize();
double deadzone = 0.02;
// Main loop.
bool done = false;
while( ! done )
{
// Keep the list of joysticks up-to-date.
Joy.FindJoysticks();
// Handle all user input.
SDL_Event event;
while( SDL_PollEvent( &event ) )
{
// Let the JoystickManager track events relevant to it.
Joy.TrackEvent( &event );
// FIXME: Handle single-press events here (next target, etc).
// Don't handle button-held-down events like firing (see below).
if( event.type == SDL_QUIT )
done = true;
}
// Read joystick 0 analog axes.
double roll = Joy.Axis( 0, 0, deadzone );
double pitch = Joy.Axis( 0, 1, deadzone );
double yaw = Joy.Axis( 0, 3, deadzone );
double throttle = Joy.AxisScaled( 0, 2, 1., 0., 0., deadzone );
// Read joystick 0 buttons held down.
bool firing = Joy.ButtonDown( 0, 0 );
// FIXME: Update game objects and draw graphics.
}
I found a weird behaviour in SDL2:
If no events are put into the queue, try adding the following before the SDL_Init call:
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1");
Are you sure joystick points to a valid joystick?
You state that you're getting it in your Constructor... does that contructor happen to be called before you initialize SDL with SDL_INIT_JOYSTICK? This could happen if your player is a global variable.
Make sure that in order you:
Init the Joystick subsystem, either by adding it to your SDL_Init with | SDL_INIT_JOYSTICK or by calling SDL_InitSubSystem(SDL_INIT_JOYSTICK);
Check SDL_NumJoysticks() > 0
Get joystick 0: joystick = SDL_JoystickOpen(0);
Enable events: SDL_JoystickEventState(SDL_ENABLE);
Process your events with SDL_PollEvent
At the end of your program, close your joystick: SDL_JoystickClose(joystick);
Also, make sure the joystick is properly detected in Windows and reports its inputs properly.
Looks like your SDL isn't init proper.
replace
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)
with
SDL_Init(SDL_INIT_EVERYTHING)
Is this SDL 1.2 or 2.0? In my case, on 2.0 SDL_PollEvent(&event) didn't actually put any data in the event struct. After that call, I had to use SDL_JoystickGetAxis(joystick_id, axis) and friends to get data.
So in your case, try to move the SDL_JoystickGetAxis call out of the if-test on event-type.
If you call SDL_NumJoysticks to get the number of controllers connected, then call SDL_JoystickOpen which returns a joystick identifier before your game loop then you will receive the SDL_JOYAXISMOTION events.
e.g.
int num_joy;
num_joy = SDL_NumJoysticks();
printf("%d joysticks found\n", num_joy);
for(int i = 0; i < num_joy; i++)
{
SDL_Joystick *joystick = SDL_JoystickOpen(i);
printf("Joystick name: %s\n", SDL_JoystickName(joystick));
}
SDL_Event event;
bool quit = false;
// Game loop
while(!quit)
{
// event loop
while(SDL_PollEvent(&event))
{
if (event.type == SDL_JOYAXISMOTION)
{
printf("Joystick______EVENT!\n");
}
// etc.....
See https://wiki.libsdl.org/SDL_JoystickName
I do not know how this can help you, but I do know that pygame supports joystick. And pygame is the python port of the SDL library. If everything fails, I guess you can always write that particular piece of code in python.

Best algorithm for syntax highlight (WINAPI)

I write a program on WINAPI. I must to implement syntax highlight. At this moment the I using following algorithm:
void PaintWords(const char *SearchWord,COLORREF rgb)
{
counter = TabCtrl_GetCurSel(TabControl_hWnd);
ft.chrg.cpMin = 0;
ft.chrg.cpMax = GetWindowTextLength(hWnd);
ft.lpstrText = (LPCSTR)SearchWord; //keyword
do
{
int poe_p = SendMessage(hWnd, EM_FINDTEXTEX, FR_DOWN | FR_WHOLEWORD | FR_MATCHCASE, (LPARAM)&ft);
if(poe_p != -1)
{
int selword = SendMessage(hWnd, EM_EXSETSEL,0,(LPARAM)&ft.chrgText);
ZeroMemory(&chd, sizeof(chd));
chd.cbSize = sizeof(CHARFORMAT);
chd.dwMask = CFM_SIZE | CFM_FACE | CFM_COLOR | CFM_CHARSET;
chd.crTextColor = rgb;
chd.bPitchAndFamily = FW_THIN;
lstrcpy(chd.szFaceName , "Courier New");
SendMessage(hWnd,EM_SETCHARFORMAT,SCF_WORD|SCF_SELECTION,(LPARAM)&chd);
ft.chrg.cpMin = ft.chrgText.cpMax;
}
else
{
break;
}
}while(ft.chrg.cpMin != ft.chrg.cpMax);
}
This code is too slow, because this is not best option, flicker is visible.
I interested in other variants.
I think you need to use double buffering to reduce the flicker. Other than that, you should not use SendMessage (or even PostMessage) to any window (within same thread). Why selection must happen in your syntax-highlighting paint code?
One of the article on double buffer is this.
I have come across this project's RichTextbox, which is used as an xml editor: http://xpathvisualizer.codeplex.com/SourceControl/changeset/view/42057#XPathVisualizer/CustomControls/RichTextBoxEx.cs
it's in C#, but the messages sent are visible.
When using this TextBox, before highlighting the text the BeginUpdateAndSuspendEvents function should be called.
public IntPtr BeginUpdateAndSuspendEvents()
{
// Stop redrawing:
User32.SendMessage(this.Handle, (int) User32.Msgs.WM_SETREDRAW, 0, IntPtr.Zero);
// Stop sending of events:
IntPtr eventMask = User32.SendMessage(this.Handle, User32.Msgs.EM_GETEVENTMASK, 0, IntPtr.Zero);
return eventMask;
}
This function prevents redrawing while you are working on the text, after you finish editing, you should call
public void EndUpdateAndResumeEvents(IntPtr eventMask)
{
// turn on events
User32.SendMessage(this.Handle, User32.Msgs.EM_SETEVENTMASK, 0, eventMask);
// turn on redrawing
User32.SendMessage(this.Handle, User32.Msgs.WM_SETREDRAW, 1, IntPtr.Zero);
NeedRecomputeOfLineNumbers();
this.Invalidate();
}
Double buffering does not solve this problem because it will not stop the paints from occurring, highlighting an editor without disabling the paint event can cause the program to halt for more than 5 minutes depending on the size of the file and the number of words to be highlighted.

how to set "smart" breakpoint in Xcode when method returns a specific value?

I have a method which returns a bool value, with several exit points.
However, it does not seem to work correctly, so I would like to set an automatic breakpoint to see when it returns a YES value, so I can check all the variables and calculations in the debugger.
I would like to stop the debugger whenever a YES value is returned.
I have a similar smart breakpoint set for objc_exception_throw, so I know it's possible, I am just not sure how.
(In case it helps anyone, the way you can set the exception breakpoint: in the Breakpoints window (Run -> Show -> Breakpoints) enter objc_exception_throw as "Breakpoint", and libobjc.A.dylib as "Location")
EDIT: the specific code I would like to use it for:
- (BOOL)collisionOccured {
// Assumption: helicopter is of square shape (collision calculated by radius), walls are rectangles
// This approach is based on the solution seen here: http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection/402010#402010
float helicopterImageWidth = [helicopter texture].contentSize.width;
float wallImageWidth = [[walls lastObject] texture].contentSize.width;
float wallImageHeight = [[walls lastObject] texture].contentSize.height;
float helicopterCollisionRadius = helicopterImageWidth * 0.4f;
CGPoint helicopterPosition = helicopter.position;
int numWalls = [walls count];
for (int i = 0; i < numWalls; i++) {
CCSprite *wall = [walls objectAtIndex:i];
if ([wall numberOfRunningActions] == 0) {
// The wall is not moving, we can skip checking it.
continue;
}
CGPoint wallPosition = wall.position;
float helicopterDistanceX = abs(helicopterPosition.x - wallPosition.x - wallImageWidth/2);
float helicopterDistanceY = abs(helicopterPosition.y - wallPosition.y - wallImageHeight/2);
if (helicopterDistanceX > (wallImageWidth/2 + helicopterCollisionRadius)) { return NO; }
if (helicopterDistanceY > (wallImageHeight/2 + helicopterCollisionRadius)) { return NO; }
if (helicopterDistanceX <= (wallImageWidth/2)) { return YES; }
if (helicopterDistanceY <= (wallImageHeight/2)) { return YES; }
float cornerDistance_sq = powf((helicopterDistanceX - wallImageWidth/2), 2) +
powf((helicopterDistanceY - wallImageHeight/2), 2);
return (cornerDistance_sq <= powf(helicopterCollisionRadius, 2));
}
// this should not occur
return NO;
}
This method is called via
- (void)update:(ccTime)delta {
if ([self collisionOccured]) {
NSLog(#"A collision occured");
}
}
The problem is that the update method takes delta (time passed) as argument, so I can't check what's happening frame by frame -- whenever I continue the execution, I am presented with a different scene.
(I am using cocos2d in the code)
You can set conditional breakpoints. With a slight tweak to update:
- (void)update:(ccTime)delta {
BOOL collided = [self collisionOccured];
if (collided) {
NSLog(#"A collision occured");
}
}
you can set a breakpoint as normal after the BOOL's assignment (i.e. on the if line), then right-click on the blue breakpoint arrow and select "Show Message Bubble", and add collided as the Condition. The extra variable should get optimized away in Release build mode.
If you're using a local return variable:
- (BOOL)someMethod {
BOOL ret = NO;
if (something) {
ret = YES;
} else if (something_else) {
ret = YES;
}
// ... and so on
return ret;
}
You can just set a watch point on ret
Otherwise, you're probably stuck with stepping through the code—hopefully some clever combination of conditional breakpoints will help you not have to break on every invocation. Setting a method breakpoint like you do with objc_exception_throw wouldn't work, because it will stop on every invocation, and breaking on the return value at the calling site is too late to figure out how you got there.
If you can post the code, we may be able to give more specific help as to a debugging strategy. Good luck. :-)

Resources