暴米花 发表于 2006-5-12 19:03:00

BITBLT贴位图刷新时图象闪烁的问题

<b>关于BITBLT贴位图刷新时图象闪烁的问题</b><br/><br/>最近尝试了一下用BITBLT贴位图,并在点击鼠标时使图象移动,开始时窗口不能强制重画,现在用了invalidate之后,图象能动了,可是图象闪烁的厉害,请问如何解决,代码如下:<br/>#include&nbsp;"Game.h"<br/>#include&nbsp;&lt;windows.h&gt;<br/>#define&nbsp;MAX_LOADSTRING&nbsp;100<br/>#define&nbsp;SCREEN_HEIGHT&nbsp;480<br/>#define&nbsp;SCREEN_WIDTH&nbsp;640 <p></p><p>#define&nbsp;KEYDOWN(vk_code)&nbsp;((GetAsyncKeyState(vk_code)&nbsp;&amp;&nbsp;0x8000)&nbsp;?&nbsp;1&nbsp;:&nbsp;0)<br/>#define&nbsp;KEYUP(vk_code)&nbsp;&nbsp;&nbsp;((GetAsyncKeyState(vk_code)&nbsp;&amp;&nbsp;0x8000)&nbsp;?&nbsp;0&nbsp;:&nbsp;1)</p><p>int&nbsp;Game_Init(void&nbsp;*parms&nbsp;=&nbsp;NULL,&nbsp;int&nbsp;num_parms&nbsp;=&nbsp;0);<br/>int&nbsp;Game_ShutDown(void&nbsp;*parms&nbsp;=&nbsp;NULL,&nbsp;int&nbsp;num_parms&nbsp;=&nbsp;0);<br/>int&nbsp;Game_Main(void&nbsp;*parms&nbsp;=&nbsp;NULL,&nbsp;int&nbsp;num_parms&nbsp;=&nbsp;0);</p><p><br/>iPos&nbsp;iPosSence(0,0);</p><p>//&nbsp;全局变量:<br/>HINSTANCE&nbsp;hInst; //&nbsp;当前实例<br/>TCHAR&nbsp;szTitle; //&nbsp;标题栏文本<br/>TCHAR&nbsp;szWindowClass; //&nbsp;主窗口类名<br/>HBITMAP hSence;<br/>HDC&nbsp;hdcMem,hdc;<br/>HWND&nbsp;hWnd;</p><p>//&nbsp;此代码模块中包含的函数的前向声明:<br/>ATOM MyRegisterClass(HINSTANCE&nbsp;hInstance);<br/>BOOL InitInstance(HINSTANCE,&nbsp;int);<br/>LRESULT&nbsp;CALLBACK WndProc(HWND,&nbsp;UINT,&nbsp;WPARAM,&nbsp;LPARAM);<br/>LRESULT&nbsp;CALLBACK About(HWND,&nbsp;UINT,&nbsp;WPARAM,&nbsp;LPARAM);</p><p><br/>int&nbsp;APIENTRY&nbsp;_tWinMain(HINSTANCE&nbsp;hInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HINSTANCE&nbsp;hPrevInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPTSTR&nbsp;&nbsp;&nbsp;&nbsp;lpCmdLine,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nCmdShow)<br/>{<br/>&nbsp; //&nbsp;TODO:&nbsp;在此放置代码。<br/>MSG&nbsp;msg;<br/>HACCEL&nbsp;hAccelTable;</p><p>//&nbsp;初始化全局字符串<br/>LoadString(hInstance,&nbsp;IDS_APP_TITLE,&nbsp;szTitle,&nbsp;MAX_LOADSTRING);<br/>LoadString(hInstance,&nbsp;IDC_GAME,&nbsp;szWindowClass,&nbsp;MAX_LOADSTRING);<br/>MyRegisterClass(hInstance);</p><p>//&nbsp;执行应用程序初始化:<br/>if&nbsp;(!InitInstance&nbsp;(hInstance,&nbsp;nCmdShow))&nbsp;<br/>{<br/>return&nbsp;FALSE;<br/>}</p><p>hAccelTable&nbsp;=&nbsp;LoadAccelerators(hInstance,&nbsp;(LPCTSTR)IDC_GAME);</p><p>Game_Init();</p><p>//&nbsp;主消息循环:<br/>while(TRUE)<br/>{<br/>if&nbsp;(PeekMessage(&amp;msg,NULL,0,0,PM_REMOVE))<br/>{&nbsp;<br/>if&nbsp;(msg.message&nbsp;==&nbsp;WM_QUIT)<br/>break;<br/>TranslateMessage(&amp;msg);<br/>DispatchMessage(&amp;msg);<br/>}&nbsp;<br/>Game_Main();<br/>Sleep(30);<br/>}&nbsp;</p><p>Game_ShutDown();<br/>return&nbsp;(int)&nbsp;msg.wParam;<br/>}</p><p>//<br/>//&nbsp;&nbsp;函数:&nbsp;MyRegisterClass()<br/>//<br/>//&nbsp;&nbsp;目的:&nbsp;注册窗口类。<br/>//<br/>//&nbsp;&nbsp;注释:&nbsp;<br/>//<br/>//&nbsp;&nbsp;&nbsp;&nbsp;仅当希望在已添加到&nbsp;Windows&nbsp;95&nbsp;的<br/>//&nbsp;&nbsp;&nbsp;&nbsp;“RegisterClassEx”函数之前此代码与&nbsp;Win32&nbsp;系统兼容时,<br/>//&nbsp;&nbsp;&nbsp;&nbsp;才需要此函数及其用法。调用此函数<br/>//&nbsp;&nbsp;&nbsp;&nbsp;十分重要,这样应用程序就可以获得关联的<br/>//&nbsp;&nbsp;&nbsp;“格式正确的”小图标。<br/>//<br/>ATOM&nbsp;MyRegisterClass(HINSTANCE&nbsp;hInstance)<br/>{<br/>WNDCLASSEX&nbsp;wcex;</p><p>wcex.cbSize&nbsp;=&nbsp;sizeof(WNDCLASSEX);&nbsp;</p><p>wcex.style =&nbsp;CS_HREDRAW&nbsp;|&nbsp;CS_VREDRAW;<br/>wcex.lpfnWndProc =&nbsp;(WNDPROC)WndProc;<br/>wcex.cbClsExtra =&nbsp;0;<br/>wcex.cbWndExtra =&nbsp;0;<br/>wcex.hInstance =&nbsp;hInstance;<br/>wcex.hIcon =&nbsp;LoadIcon(hInstance,&nbsp;(LPCTSTR)IDI_GAME);<br/>wcex.hCursor =&nbsp;LoadCursor(NULL,&nbsp;IDC_ARROW);<br/>wcex.hbrBackground =&nbsp;(HBRUSH)(COLOR_WINDOW+1);<br/>wcex.lpszMenuName =&nbsp;(LPCTSTR)IDC_GAME;<br/>wcex.lpszClassName =&nbsp;szWindowClass;<br/>wcex.hIconSm =&nbsp;LoadIcon(wcex.hInstance,&nbsp;(LPCTSTR)IDI_GAME);</p><p>return&nbsp;RegisterClassEx(&amp;wcex);<br/>}</p><p>//<br/>//&nbsp;&nbsp;&nbsp;函数:&nbsp;InitInstance(HANDLE,&nbsp;int)<br/>//<br/>//&nbsp;&nbsp;&nbsp;目的:&nbsp;保存实例句柄并创建主窗口<br/>//<br/>//&nbsp;&nbsp;&nbsp;注释:&nbsp;<br/>//<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在此函数中,我们在全局变量中保存实例句柄并<br/>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;创建和显示主程序窗口。<br/>//<br/>BOOL&nbsp;InitInstance(HINSTANCE&nbsp;hInstance,&nbsp;int&nbsp;nCmdShow)<br/>{<br/>int&nbsp;xScrn,&nbsp;yScrn,x,y;<br/>HDC&nbsp;hScrDC;<br/>hInst&nbsp;=&nbsp;hInstance;&nbsp;//&nbsp;将实例句柄存储在全局变量中<br/>hScrDC&nbsp;=&nbsp;CreateDC("DISPLAY",&nbsp;NULL,&nbsp;NULL,&nbsp;NULL);&nbsp;<br/>xScrn&nbsp;=&nbsp;GetDeviceCaps(hScrDC,&nbsp;HORZRES);&nbsp;<br/>yScrn&nbsp;=&nbsp;GetDeviceCaps(hScrDC,&nbsp;VERTRES);&nbsp;<br/>x&nbsp;=&nbsp;(xScrn&nbsp;-&nbsp;SCREEN_WIDTH)/2;<br/>y&nbsp;=&nbsp;(yScrn&nbsp;-&nbsp;SCREEN_HEIGHT)/2;<br/>hWnd&nbsp;=&nbsp;CreateWindow(szWindowClass,&nbsp;szTitle,&nbsp;WS_OVERLAPPEDWINDOW,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x,&nbsp;y,&nbsp;SCREEN_WIDTH,&nbsp;SCREEN_HEIGHT,&nbsp;NULL,&nbsp;NULL,&nbsp;hInstance,&nbsp;NULL);<br/>hSence=&nbsp;LoadBitmap&nbsp;(hInst,&nbsp;MAKEINTRESOURCE(IDB_SENCE))&nbsp;;<br/>if&nbsp;(!hWnd)<br/>{<br/>return&nbsp;FALSE;<br/>}</p><p>ShowWindow(hWnd,&nbsp;nCmdShow);<br/>UpdateWindow(hWnd);</p><p>return&nbsp;TRUE;<br/>}</p><p>//<br/>//&nbsp;&nbsp;函数:&nbsp;WndProc(HWND,&nbsp;unsigned,&nbsp;WORD,&nbsp;LONG)<br/>//<br/>//&nbsp;&nbsp;目的:&nbsp;处理主窗口的消息。<br/>//<br/>//&nbsp;&nbsp;WM_COMMAND -&nbsp;处理应用程序菜单<br/>//&nbsp;&nbsp;WM_PAINT -&nbsp;绘制主窗口<br/>//&nbsp;&nbsp;WM_DESTROY -&nbsp;发送退出消息并返回<br/>//<br/>//<br/>LRESULT&nbsp;CALLBACK&nbsp;WndProc(HWND&nbsp;hWnd,&nbsp;UINT&nbsp;message,&nbsp;WPARAM&nbsp;wParam,&nbsp;LPARAM&nbsp;lParam)<br/>{<br/>int&nbsp;wmId,&nbsp;wmEvent;</p><p>switch&nbsp;(message)&nbsp;<br/>{<br/>case&nbsp;WM_LBUTTONDOWN:<br/>iPosSence.x+=10;<br/>break;<br/>case&nbsp;WM_COMMAND:<br/>wmId&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;LOWORD(wParam);&nbsp;<br/>wmEvent&nbsp;=&nbsp;HIWORD(wParam);&nbsp;<br/>//&nbsp;分析菜单选择:<br/>switch&nbsp;(wmId)<br/>{<br/>case&nbsp;IDM_about:<br/>DialogBox(hInst,&nbsp;(LPCTSTR)IDD_ABOUTBOX,&nbsp;hWnd,&nbsp;(DLGPROC)About);<br/>break;<br/>case&nbsp;IDM_EXIT:<br/>DestroyWindow(hWnd);<br/>break;<br/>default:<br/>return&nbsp;DefWindowProc(hWnd,&nbsp;message,&nbsp;wParam,&nbsp;lParam);<br/>}<br/>break;<br/>case&nbsp;WM_PAINT:<br/>break;<br/>case&nbsp;WM_DESTROY:<br/>PostQuitMessage(0);<br/>break;<br/>default:<br/>return&nbsp;DefWindowProc(hWnd,&nbsp;message,&nbsp;wParam,&nbsp;lParam);<br/>}<br/>return&nbsp;0;<br/>}</p><p>//&nbsp;“关于”框的消息处理程序。<br/>LRESULT&nbsp;CALLBACK&nbsp;About(HWND&nbsp;hDlg,&nbsp;UINT&nbsp;message,&nbsp;WPARAM&nbsp;wParam,&nbsp;LPARAM&nbsp;lParam)<br/>{<br/>switch&nbsp;(message)<br/>{<br/>case&nbsp;WM_INITDIALOG:<br/>return&nbsp;TRUE;</p><p>case&nbsp;WM_COMMAND:<br/>if&nbsp;(LOWORD(wParam)&nbsp;==&nbsp;IDOK&nbsp;||&nbsp;LOWORD(wParam)&nbsp;==&nbsp;IDCANCEL)&nbsp;<br/>{<br/>EndDialog(hDlg,&nbsp;LOWORD(wParam));<br/>return&nbsp;TRUE;<br/>}<br/>break;<br/>}<br/>return&nbsp;FALSE;<br/>}</p><p><br/>int&nbsp;Game_Init(void&nbsp;*parms,&nbsp;int&nbsp;num_parms)<br/>{<br/><br/>return&nbsp;0;<br/>}</p><p>int&nbsp;Game_ShutDown(void&nbsp;*parms,&nbsp;int&nbsp;num_parms)<br/>{<br/>return&nbsp;0;<br/>}</p><p>int&nbsp;Game_Main(void&nbsp;*parms,&nbsp;int&nbsp;num_parms)<br/>{<br/>PAINTSTRUCT&nbsp;ps;<br/>hdc&nbsp;=&nbsp;BeginPaint(hWnd,&nbsp;&amp;ps);<br/>hdcMem&nbsp;=&nbsp;CreateCompatibleDC&nbsp;(hdc)&nbsp;;<br/>SelectObject&nbsp;(hdcMem,&nbsp;hSence)&nbsp;;<br/>BitBlt&nbsp;(hdc,&nbsp;0,0,&nbsp;SCREEN_WIDTH,&nbsp;SCREEN_HEIGHT,&nbsp;hdcMem,&nbsp;iPosSence.x,&nbsp;iPosSence.y,&nbsp;SRCCOPY)&nbsp;;<br/>DeleteDC(&nbsp;hdcMem&nbsp;); <br/>EndPaint(hWnd,&nbsp;&amp;ps);<br/>RECT&nbsp;rctA;<br/>rctA.left&nbsp;=&nbsp;0;<br/>rctA.top&nbsp;=&nbsp;0;<br/>rctA.right&nbsp;&nbsp;=&nbsp;640;<br/>rctA.bottom&nbsp;=&nbsp;480;<br/>::InvalidateRect(hWnd,&amp;rctA,TRUE);<br/>return&nbsp;0;<br/>}</p>

van_yb 发表于 2006-6-13 11:18:00

<p>看不懂~~漂过路过~</p><p></p>

jalang 发表于 2006-6-14 14:40:00

<p>观望</p>

DoubleCai 发表于 2006-8-5 18:42:00

<p>应该弄成双缓冲的。</p><p>建立一个离屏的DC,先画到这个DC上,然后在BltBit到窗口DC上就行了。</p>
[此贴子已经被作者于2006-8-5 18:47:47编辑过]

YANGEdisonD 发表于 2006-8-26 10:06:00

晕..这么深奥..

billwillman 发表于 2006-10-1 22:29:00

<p>你在每次循环上都</p><p>CreateCompatibleDC&nbsp;(hdc)&nbsp;;</p><p>创建内存DC,DeleteDC,删除DC,这样在效率上不好,你可以创建一个内存DC,在每次循环上只使用它就可以了.<br/>你可以控制窗体属性让它禁止刷新窗体.</p><p>如果还觉得效率不高,可以使用DIRECTX</p>
页: [1]
查看完整版本: BITBLT贴位图刷新时图象闪烁的问题