首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

双缓存窗口重绘有关问题。大侠们帮忙看一看吧。

2012-05-27 
双缓存窗口重绘问题。。。大侠们帮忙看一看吧。。。c++ API窗口重绘问题,用了双缓冲,虽然不再闪频,但是很多新问

双缓存窗口重绘问题。。。大侠们帮忙看一看吧。。。
c++ API窗口重绘问题,用了双缓冲,虽然不再闪频,但是很多新问题出现了。。。
第一是CPU占用很高,几乎到了70%-80%
第二就是文字、线条等等设置了颜色却无显示,一律为黑色。。。

源码如下。。。

C/C++ code
#include <iostream>#include <Windows.h>#include <WinDef.h>//辅助绘制函数void Text (HDC &hdc, int x, int y, LPCWSTR ps_string, int color){    SetTextColor(hdc, color);    TextOut (hdc, x, y, ps_string, lstrlen(ps_string));    SetTextColor(hdc, 0);}void Line (HDC &hdc, int xBeg, int yBeg, int xEnd, int yEnd, int color){    HPEN hPen;    hPen = CreatePen(PS_SOLID, 0, color);    SelectObject(hdc, hPen);    MoveToEx (hdc, xBeg, yBeg, NULL);    LineTo (hdc ,xEnd, yEnd);    DeleteObject(hPen);}void FRect(HDC &hdc, RECT* re, HBRUSH hBrush){    SelectObject(hdc, hBrush);    FillRect(hdc, re, hBrush);}class Mag{public:    HWND hwnd;    MSG msg;    RECT winRect;        HDC dc;          //主DC    HDC bgdc;        //缓存DC    HBRUSH bgbrush;    HBITMAP bgimg;        void flush();    //重绘函数    void Init();     //初始化函数    LRESULT keys(HWND &hwnd, UINT &msg, WPARAM &wparam, LPARAM &lparam);    //消息处理函数};void Mag::Init(){    this->bgbrush = CreateSolidBrush(0xffffff);    this->dc = GetDC(this->hwnd);    this->bgdc = CreateCompatibleDC(this->dc);    this->bgimg = CreateCompatibleBitmap(this->bgdc, this->width ,this->height);    SelectObject(this->bgdc, this->bgbrush);    SelectObject(this->bgdc, this->bgimg);}void Mag::flush(){    //在缓存DC上绘制    FRect(this->bgdc, &this->winRect, this->bgbrush);       Line(this->bgdc, 0, 1, 100, 1, 0x595ade);         //这里,绘制的颜色设定了非黑色,但实际绘制出来的还是黑色    Line(this->bgdc, 0, 10, 100, 10, 0x195ade);    //这里也是    Text(this->bgdc, 10, 30, TEXT("测试文本"), RGB(120,50,160) );    //这里也是    //在主DC上绘制    BitBlt (this->mag->dc, 0, 0, this->mag->width, this->mag->height, this->mag->bgdc, 0, 0, SRCCOPY);}LRESULT Mag::keys(HWND &hwnd, UINT &msg, WPARAM &wparam, LPARAM &lparam){    switch (msg)    {    case WM_PAINT:        this->flush();        return 0;    case WM_CLOSE:        DestroyWindow(hwnd);        return 0;    case WM_DESTROY:        {            PostQuitMessage (0);            return 0;        }    default:        return DefWindowProc (hwnd, msg, wparam, lparam);    }}//创建Mag类Mag mag = Mag()//创建窗口//消息处理主函数LRESULT Mag::keys(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam){    return mag.body->keys(hwnd, msg, wparam, lparam);}int WINAPI WinMain(......){//省去一堆创建窗口的代码mag.Init();                      //主动初始化ShowWindow (mag.hwnd, iCmdShow);UpdateWindow(mag.hwnd);while (GetMessage(&mag.msg, NULL, 0, 0) )    {        TranslateMessage (&mag.msg);        DispatchMessage (&mag.msg);        UpdateWindow(mag.hwnd);    }return mag.msg.wParam;}//源码结束



高手们。。。大侠们。。。帮帮忙呀。。。。。。

[解决办法]
既然你处理了 WM_PAINT 消息,可见你并不是想用来显示动画或者说自己管理整个的窗口界面刷新。

那么首先你应该在每一次处理WM_PAINT消息的时候,先调用BeginPaint函数来获取DC以使无效区域置为有效,画完后调用EndPaint。否则就会不停的有WM_PAINT消息产生,你的CPU就完蛋了,就算你要实现动画效果那么你就得加延时控制帧率。

其次你代码的
while (GetMessage(&mag.msg, NULL, 0, 0) )
{
TranslateMessage (&mag.msg);
DispatchMessage (&mag.msg);
UpdateWindow(mag.hwnd);
}
部分 UpdateWindow 调用是不需要的。


至于画出的线条颜色,和文字颜色等问题
void Mag::Init()
{
this->bgbrush = CreateSolidBrush(0xffffff);
this->dc = GetDC(this->hwnd);
this->bgdc = CreateCompatibleDC(this->dc);
this->bgimg = CreateCompatibleBitmap(this->bgdc, this->width ,this->height); //这里
SelectObject(this->bgdc, this->bgbrush);
SelectObject(this->bgdc, this->bgimg);


}
Init 函数中
this->bgimg = CreateCompatibleBitmap(this->bgdc, this->width ,this->height); 
这一句CreateCompatibleBitmap的第一个参数应为 this->dc,不是bgdc。

另外你mag类中初始化创建的资源应在析构时释放 不知道是不是你代码省略了。。。。。。等等

最后你的 内存DC和兼容位图等恐怕得每次重画的时候重新创建
[解决办法]
验证了4楼的说法
this->bgimg = CreateCompatibleBitmap(this->dc, this->width ,this->height);
果然紫色字体可以显示了。

但 BeginPaint函数 不一定使用;
参考 VC绘制位图--BeginPaint()与GetDC()的区别和双缓冲 http://blog.csdn.net/liuxingbin/article/details/5635902

热点排行