hello everyone,
i'm hoping someone can help me with this problem. i'm attempting to draw in a window without flicker. the stuff i've read indicates a bacbuffer be used and it BitBlt'd to the actual w as the final act before returning FALSE to windows. a simple program: left click anywhere in its window and a bitmap will be drawn there. Quickly pressing left mouse button and it flickers.
Also if an obscuring window dragged downwards and exposing this window it violently flickers! - i've solved this particular problem.
/*
see mousetest for getting cursor clicked pos
next job - use backbuffer to remove flicker
Hmmm! doesn't stop flicker if left mouse button clicked fast
or if an obscuring window dragged downwards and exposing this window!
*/
#include <windows.h>
// create mem leak report in Debug tab of 'Output' tab of Visual Studio
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define IDI_ICON1 101
#define IDB_BITMAP1 102
HINSTANCE hInst;
//byte IX, IY;
WORD IX= 25;
WORD IY= 30;
int flag = 0;
void DrawHello2 ( HWND hwnd, WPARAM wParam, LPARAM lParam, int flag )
{
// uses a backbuffer - should be no flicker but there is.
// placing a breakpoint at
//BitBlt-1 and/or
//BitBlt-2
// below proves nothing direct to screen!?
HDC hDC1;
HBITMAP hBitmap, hBitmap2;
HPALETTE hPalette;
BITMAP bm2;
PAINTSTRUCT ps;
RECT xrect, xrect2;
HDC hBkbDC, hBkbDC2;
int hbkmd, hgetsysc;
HGDIOBJ hBrush = 0, hsavsel = 0, hsavsel2 = 0;
COLORREF colref;
int RGB1 = 0x080; // red
int RGB2 = 0x80FFFF; // yellow
int RGB3 = 0xFFFF80; // cyan
int RGB4 = 0x8F8F80; // grey
int RGB5 = 0xEE8844; //
int RGB6 = 0x88AACC; //
int RGB7 = 0x00FF00; //
int RGB8 = 0x0; //
int RGB9 = 0x0FFFFFF; //
int icbmx = 0;
int icbmy = 0;
int inty = 0;
int nXbmp = 190;
int nYbmp = 70;
int intb = 0;
LPCTSTR lpszImg2;
hPalette = 0;
hDC1 = BeginPaint ( hwnd, &ps ); // when DrawHello replaced with DrawHello2
if (hDC1 != NULL) {
// Followimg so we can copy backbuffer hBitmap to actual screens bitmap buffer
GetClientRect( (HWND) hwnd, &xrect );
icbmx = xrect.right - xrect.left;
icbmy = xrect.bottom - xrect.top;
hBitmap = CreateCompatibleBitmap ( hDC1, icbmx, icbmy );
// Select that bitmap into the object, preserve old for DeleteDC
hBkbDC = CreateCompatibleDC ( hDC1 ); // Create a compatible DC
hsavsel = SelectObject ( hBkbDC, hBitmap );
if ( flag ) {
//+++ Followimg just to draw text in the Client area
hgetsysc = GetSysColor ( COLOR_WINDOW );
hBrush = CreateSolidBrush ( hgetsysc ); // without this no colour chg
//+++ Followimg just to draw text in the Client area
hgetsysc = GetSysColor ( COLOR_WINDOW );
hBrush = CreateSolidBrush ( hgetsysc ); // without this no colour chg
// see WinMain _CrtSetDbgFlag for mem leak report if multiple prog exits
// _CrtDumpMemoryLeaks(); // use this if single prog exit.
return 1;
// return 0;
}
// only comes here once at start
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR d3, int nCmdShow )
{
MSG msg;
HWND hwnd;
WNDCLASS wndClass;
int * IPAddrArray;
HDC hDC;
LPCTSTR lpszImg;
// create mem leak report in Debug tab of 'Output' tab of Visual Studio
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
hInst = hInstance;
IPAddrArray = (int *)malloc(1024);
memset ( IPAddrArray, 0, 32 ); // zero it out
// free ( IPAddrArray ); // will report mem leak
if (hPrevInstance == NULL)
{
lpszImg = "C:\\cpp\\HiyaWin4\\Ist.ico";
C:\WinDDK\7600.16385.1\inc\api,C:\Program Files\Microsoft SDKs\Windows\v6.1\Include - for GDI+
change _CONSOLE to _WINDOWS
add ' _CRTDBG_MAP_ALLOC' to Preprocessor definitions
- link step - input
C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib - for GDI+
add gdiplus.lib OR place following in .cpp file - for GDI+
#pragma comment (lib, "Gdiplus.lib") - for GDI+
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
// Create an off-screen DC for double-buffering
hdcMem = CreateCompatibleDC(hdc);
hOld = SelectObject(hdcMem, hbmMem);
// Draw into hdcMem here
DrawHello2 ( hdcMem, flag );
// Transfer the off-screen DC to the screen
BitBlt(hdc, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);
// Free-up the off-screen DC
SelectObject(hdcMem, hOld);
DeleteObject(hbmMem);
DeleteDC (hdcMem);
EndPaint(hwnd, &ps);
return 0;
Hmmm! sounds like a good plan thanks Thomas. will try it when i get home. are you saying the oriinal didn't flicker or the change you have implemented? the original does flicker on my XP SP3 - i'm still in the dark ages.
Many thanks.
case WM_PAINT:
hDC = BeginPaint ( hwnd, &ps ); // when DrawHello replaced with DrawHello2
DrawHello2 ( hwnd, wParam, lParam, flag ); // does EndPaint
EndPaint ( hwnd, &ps );
//Sleep (200);
DeleteDC( hDC );
return 0; // FALSE 0: TRUE 1:
and when i obscured my window with another and slowly dragged it downwards to reveal my window it flickered like crazy man. when i changed it to
case WM_PAINT:
DrawHello2 ( hwnd, wParam, lParam, flag ); // does EndPaint
return 0; // FALSE 0: TRUE 1:
it didn't flicker at all when repeating this operation! It didn't stop the fast mouse button press flicker though. Guess this should have been a huge hint to do what you have proposed.
The good news is that having implemented your suggestion it works with absolutely no flicker removing the need to clear the actual screens bitmap as i had to in the orig program posted above. as in
// FillRect ( hDC1, &xrect, (HBRUSH) hBrush ); // clear screen
I suspect it was this extra FillRect that caused the flicker!?
In fact it was, i've just tried it. writing same pixel twice !
It even works when maximized. Yee-hah!
You're a real star Thomas. Many thanks for your time. Mucho Kudos.
mind you i still don't fully understand one crucial thing. when i commented out the FillRect ( hDC1... in the original posted program the flicker did stop but the old contents remainded and was thus continually added to. perhaps you can let me know what i'm missing on this Thomas?
The problem I see is that FillRect ( hDC1) is the normal DC. All the painting should be on the background DC. That's why I suggested to create a the background DC in WM_PAINT and pass it to DrawHello2.
yes i understand that thanks Thomas. unfortunately in my orig posted prog if i didn't include that then the results on the screen were a combination of all that went before. this is what i don't comprehend as the bacbuffer shuold have overwritten the previous screens contents. i was the last thing done.
perhaps TRANSPARENT has something to do with it? i'll do some more testing.
Cheers.
finally got time to try a few things. silly me had SRCAND in the orig when BitBlt'ng to the main screens bitmap. Oh well at least i understand it now.
my final WM_PAINT is this and works.