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