精华内容
下载资源
问答
  • c++控制台程序双缓冲解决闪屏

    千次阅读 2017-12-10 11:16:58
    #include #include using namespace std; #define MAP_HEGHT 20 #define MAP_WIGHT 30 void map(int CountX, int CountY); int main() { HANDLE hOutput; COORD coord = { 0, 0 };...hOutput = GetStdHand
    #include<iostream>
    #include<Windows.h>
    using namespace std;
    #define MAP_HEGHT  20
    #define MAP_WIGHT  30
    void map(int CountX, int CountY);
    int main()
    {
    HANDLE hOutput;
    COORD coord = { 0, 0 };
    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    int BeginTime = GetTickCount();
    while (true)
    {
    if (GetTickCount() - 1000 / 6 >= BeginTime)
    {
    SetConsoleCursorPosition(hOutput, coord);
    map(MAP_HEGHT, MAP_WIGHT);
    BeginTime = GetTickCount();
    }
    }
    cin.get();
    }
    void map(int CountX, int CountY)
    {
    for (int x = 0; x < CountX; x++)
    {
    for (int y = 0; y < CountY; y++)
    {
    cout << "□";
    }
    cout << endl;
    }
    }
    展开全文
  • 主要介绍了C#双缓冲实现方法,结合实例形式分析了C#双缓冲的具体步骤与相关技巧,可实现防止闪屏的功能,需要的朋友可以参考下
  • 百度了一下,使用【双缓冲解决闪屏,其实关于闪屏的问题,3年前我也收藏过相关的文章,现在连我自己都忘记了。 参考资料:https://bbs.csdn.net/topics/350077253 @码侬 //创建内存DC HDC hdcMem = ...

    最近刚刚学习了使用 gdi+ 在窗口上绘制 png 图片, 但还是遇到一个老问题, 就是闪屏的情况。

    百度了一下,使用【双缓冲】解决闪屏,其实关于闪屏的问题,3年前我也收藏过相关的文章,现在连我自己都忘记了。

     

    参考资料: https://bbs.csdn.net/topics/350077253 @码侬

    //创建内存DC
         HDC hdcMem = CreateCompatibleDC(hdc);
         //创建一个bmp内存空间
         HBITMAP hBmp = CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_HEIGHT);
         //将bmp内存空间分配给内存DC
         HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);
        
         //这是使用者需要绘制的画面,全部往内存DC绘制
          // 绘制代码.......................
    
         如:
          Rectangle(hdcMem,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
         
        
         //将内存DC的内容复制到屏幕显示DC中,完成显示
         BitBlt(hdc,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,hdcMem,0,0,SRCCOPY);
         //清除资源
         SelectObject(hdcMem,hOldSel);    
         DeleteDC(hdcMem);    
    
    另外,重载OnEraseBkgnd(CDC* pDC),在该函数中不要绘制背景,中直接返回TRUE。
    
    也就是:
    
    switch(message)
        {
            case WM_ERASEBKGND:
            {
    
                // 重载OnEraseBkgnd(CDC* pDC),在该函数中不要绘制背景,中直接返回TRUE。
    
                return TRUE;
            }

     

    还有一篇类似的资料: https://blog.csdn.net/lanyzh0909/article/details/5913836

     

    另外有两篇:基于GDI+实现双缓冲技术  https://blog.csdn.net/woaisia/article/details/46788965      https://blog.csdn.net/htt9931/article/details/28641039

    下面这个,我没测试:

            CPaintDC dc(this);                              // device context for painting
            Graphics gr(dc.m_hDC);                          // Graphics to paint
    
    
            Rect rGdi;
            gr.GetVisibleClipBounds(&rGdi);                 // The same as the clip rect
            
            //创建缓冲区
            Bitmap clBmp(rGdi.Width, rGdi.Height);          // Mem bitmap
            Graphics* grPtr = Graphics::FromImage(&clBmp);  // As memDC
            
            //利用grPtr在clBmp缓冲区绘图
            grPtr->DrawImage(m_PngMeter,clock_Rect);
            grPtr->TranslateTransform(Pcenter.X,Pcenter.Y);
            grPtr->RotateTransform(i);
            grPtr->TranslateTransform(-Pcenter.X,-Pcenter.Y);
            grPtr->DrawImage(m_PngArrow,picRect);
            grPtr->ResetTransform();
     
            //将clBmp缓冲区绘制到窗口
            gr.DrawImage(&clBmp, rGdi); 
    
    
    delete grPtr; //注:使用完缓冲区后,一定要及时释放内才能,尤其是在OnPaint中,否则程序很快占满物理内存,崩溃!

     

    转载于:https://www.cnblogs.com/personnel/p/9339526.html

    展开全文
  • C语言游戏 缓存解决闪屏问题 详细总结

    千次阅读 多人点赞 2019-11-16 22:23:26
    而在刚学完C语言刚着手准备做C语言的小游戏时,却发现了一个问题——闪屏。 (我在网上查找了很多关于缓存,有关的解答很少,更少能够让一个完全不了解的小白一个明白的解释。下面我想和大家分享我使用...

     

    最近,应学校课程要求,要完成一个C语言课程设计。可以是写一个小游戏,或是写管理系统等。

    所以,准备做一个改版贪吃蛇:消灭小虫虫(瞎起的名字  :D)。

    之前学过Java,所以学C语言也就比较顺利。而在刚学完C语言刚着手准备做C语言的小游戏时,却发现了一个问题——闪屏

    (我在网上查找了很多关于双缓存,有关的解答很少,更少能够让一个完全不了解的小白一个明白的解释。下面我想和大家分享我使用双缓存完成了小游戏后的总结体会。希望能够一目了然。)

    编辑器 —— Dev-C++ 5.11


    先说一下,C语言来做游戏的原理:

    就是在控制台打印图案,然后使用 system("cls"); 来擦除界面,然后再打印图案的循环过程。

    闪屏现象

    我们正常打印输出内容的时候,是按顺序输出的。从第一个一直打印的最后一个。

    当我们输出的内容十分庞大的时候,第一个和最后一个会存在输出时间差。

    也就是前面先输出了,而后面你还没看到。所以会有闪屏的现象。

     

    如何解决闪屏?

    治标须治本——双缓存技术

     

    何为双缓存?

    我希望大家去看看这个网站:猛击这里

    这个网站是我理解双缓存的主要网站,何为双缓存,这位作者写得还是比较易懂的。

    不过怎么用?怎么能够用在我的C语言小游戏上?还是会让人一头雾水。

     

    (下面只针对双缓存的实现分享我的总结,不对这个游戏的原理做详解。如果有同学想了解贪吃蛇的实现原理可以去看这位笔者:猛击这里  我的消灭小虫虫以及双缓存的学习也有借鉴他。)


    Win32 API

    #include<windows.h>  头文件引用

    双缓存技术主要使用到了Win32 API

    用到的函数有:CreateConsoleScreenBuffer、WriteConsoleOutputCharacter、ReadConsoleOutputCharacter、SetConsoleActiveScreenBuffer、SetConsoleCursorInfo

    官方API文档:猛击这里

     

    CreateConsoleScreenBuffer

    简单来说就是 初始化新缓存,并配置新缓存参数。

    HANDLE WINAPI CreateConsoleScreenBuffer(
      _In_             DWORD               dwDesiredAccess,
      _In_             DWORD               dwShareMode,
      _In_opt_   const SECURITY_ATTRIBUTES *lpSecurityAttributes,
      _In_             DWORD               dwFlags,
      _Reserved_       LPVOID              lpScreenBufferData
    );
    dwDesiredAccess:控制台缓冲安全与访问权限,可取值:
        GENERIC_READ (0x80000000L),读权限
        GENERIC_WRITE (0x40000000L),写权限
    dwShareMode:共享模式,可取值:
        FILE_SHARE_READ:读共享
        FILE_SHARE_WRITE:写共享
    lpSecurityAttributes:安全属性,NULL
    dwFlags:缓冲区类型,仅可选:
        CONSOLE_TEXTMODE_BUFFER,控制台文本模式缓冲
    lpScreenBufferData:保留,NULL

    范例:

    //具体使用范例
    hOutBuf = CreateConsoleScreenBuffer(
    	GENERIC_WRITE,  //对控制台屏幕缓冲区的访问
    	FILE_SHARE_WRITE, //定义缓冲区可共享写权限
    	NULL,//安全属性默认为NULL 
    	CONSOLE_TEXTMODE_BUFFER,//缓冲区类型,固定参数 
    	NULL
    );
    
    //第一个缓存区赋值为hOutBuf,一般是创建两个缓存区(我这命名第二缓存区为:hOutput)
    
    hOutput  = CreateConsoleScreenBuffer(
    	GENERIC_WRITE,  //对控制台屏幕缓冲区的访问
    	FILE_SHARE_WRITE, //定义缓冲区可共享写权限
    	NULL,//安全属性默认为NULL 
    	CONSOLE_TEXTMODE_BUFFER,//缓冲区类型,固定参数 
    	NULL
    );

    WriteConsoleOutputCharacter

    指定一个缓存区,将需要输出的内容(这规定的类型是字符数组)输出到控制台。

    BOOL WINAPI WriteConsoleOutputCharacter(
      _In_  HANDLE  hConsoleOutput,   //控制台屏幕缓冲区的句柄。句柄必须具有GENERIC_WRITE访问权限。
      _In_  LPCTSTR lpCharacter,      //写入的字符数组指针
      _In_  DWORD   nLength,          //写入的长度
      _In_  COORD   dwWriteCoord,     //写入起始坐标,  一个COORD结构(后面讲)
      _Out_ LPDWORD lpNumberOfCharsWritten  //指向变量的指针,该变量接收实际写入的字符数。
    );

    范例:

    char score_char1[] = "012345678901234567890123456789";
    coord.Y = 1;//第一行位置输出
    WriteConsoleOutputCharacter( hOutBuf, score_char1, strlen(score_char1), coord, &bytes );
    //之前全局变量定义了: COORD coord = {0,0};  DWORD bytes = 0;

    COORD:

    typedef struct _COORD {
    SHORT X; // 横坐标
    SHORT Y; // 纵坐标
    } COORD;
    //使用范例
    COORD coord = {0,0};

     

    ReadConsoleOutputCharacter

    指定缓存区,读取控制台内容输出到字符数组。

    用法和WriteConsoleOutputCharacterA相同,不做范例。

     

    SetConsoleActiveScreenBuffer

    双缓存,顾名思义就是有两个缓存。那么这个函数就是用来切换两个缓存的。

    //设置控制台活动显示缓冲
    BOOL WINAPI SetConsoleActiveScreenBuffer(
      _In_ HANDLE hConsoleOutput //hConsoleOutput:控制台输出设备句柄
    );

    范例:

    SetConsoleActiveScreenBuffer(hOutBuf);//设置hOutBuf为活动显示的缓冲区
    
    //*...这里是设置不同缓存区的内容等操作的代码...*//
    
    SetConsoleActiveScreenBuffer(hOutput);//设置hOutput为活动显示的缓冲区,即实现了切换缓冲区

     

    SetConsoleCursorInfo

    这是一个设置光标的函数:大小,可见度。

    BOOL WINAPI SetConsoleCursorInfo(
      _In_       HANDLE              hConsoleOutput,  //控制台输出设备句柄
      _In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo //光标信息(大小、可见性)
    );

    范例:

    //隐藏两个缓冲区的光标
    CONSOLE_CURSOR_INFO cci;
    cci.bVisible = 0; // 可见度
    cci.dwSize =1;// 大小
    SetConsoleCursorInfo(hOutput, &cci);
    SetConsoleCursorInfo(hOutBuf, &cci);
    
    /*注: 这里的CONSOLE_CURSOR_INFO结构体如下:
    typedef struct _CONSOLE_CURSOR_INFO {
      DWORD dwSize;// 光标百分比厚度(1~100) 
      BOOL  bVisible;// 可见性 FALSE,0,不可见;TRUE,1,可见
      } CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO; */

    总体代码:

    #include<stdio.h>
    #include<windows.h>
    
    HANDLE hOutput,hOutBuf;  //控制台屏幕缓冲区句柄
    HANDLE houtpoint;
    COORD coord = {5,0};//初始输出位置 
    DWORD bytes = 0;
    int hop_flag = 0;  //通过指针轮流指向两个缓冲区,实现双缓冲 
    
    void printPic();
    
    int main(){
    	hOutBuf = CreateConsoleScreenBuffer(
    	    GENERIC_WRITE,  
    	    FILE_SHARE_WRITE, 
    	    NULL, 
    	    CONSOLE_TEXTMODE_BUFFER,
    	    NULL
        );
        hOutput = CreateConsoleScreenBuffer(
            GENERIC_WRITE,  
            FILE_SHARE_WRITE, 
            NULL,
            CONSOLE_TEXTMODE_BUFFER,
            NULL
        );
        
        while(1){
    		printPic();
    		Sleep(600);
    	}
    } 
    
    void printPic(){
    	hop_flag = !hop_flag; 
    	if(!hop_flag){
    		char score_char1[] = "这是一个缓存区显示内容!11111111";
    		coord.Y = 1;
    	        WriteConsoleOutputCharacter( hOutBuf, score_char1, strlen(score_char1), coord, &bytes );
    		SetConsoleActiveScreenBuffer(hOutBuf);
    	}else{
    		char score_char2[] = "这是另一个缓存区显示内容!22222222";
    		coord.Y = 1;
        	        WriteConsoleOutputCharacter( hOutput, score_char2, strlen(score_char2), coord, &bytes );
    		SetConsoleActiveScreenBuffer(hOutput);
    	}
    	
    	
    }

    运行结果:

    WriteConsoleOutputCharacter( hOutBuf, score_char1, strlen(score_char1), coord, &bytes );

    在这里,输出的是字符数组score_char1,用strlen()获得字符数组长度。当然这个要看你想要输出的长度。如果我改成:strlen(score_char1)-10

    WriteConsoleOutputCharacter( hOutBuf, score_char1, strlen(score_char1)-10, coord, &bytes );

    那结果是这样的:

     

    还有这里我定义了COORD coord = {5,0};也就是初始输出点是<5,0>,又因为coord.Y = 1;所以最后coord = {5,1}

     

    在上面输出结果中,我们还能看到有光标在闪动,如果是做游戏的话,这个光标是很碍眼的。所以就可以用我上面提到过的SetConsoleCursorInfo来隐藏光标。


     

    以上我们用的还是一维数组,只输出一行内容。当然我们可以使用二维数组,直接循环输出以二维数组横坐标和纵坐标大小的面。如下图:

    主要代码:

    ……
    #define _Y 15  //15行 
    #define _X 20  // 20列 
    
    char data[_Y][_X];//这是全局变量定义的字符数组
    ……
    
    
    int main(){
        ……//这里的代码不变,和上面一样
    }
    
    void printPic(){
    	int i,j;
    	hop_flag = !hop_flag;
    	if(!hop_flag){    //这里是每次交替,直接把hOutput或hOutBuf赋给houtpoint 
    		houtpoint = hOutput;
    	}else{
    		houtpoint = hOutBuf;
    	}
        
    	for(i = 0;i < _Y;i++){    //打印你需要的二维数组图案
    		for(j = 0;j < _X;j++){
    			if(i == 0|| i == _Y-1 || j == 0 || j == _X-1){
    				data[i][j] = '*';
    			}else{
    				data[i][j] = ' ';
    			}
    		}
    	}
    	coord.Y = 1;
    	for(i = 0;i < _Y;i++){    //循环打印每一行
    		coord.Y++;    //每次都打印到下一行
        	WriteConsoleOutputCharacter( houtpoint, data[i], _X, coord, &bytes );
    	}    //data[i]:每行的地址。 _X: 每行的长度
    
    	SetConsoleActiveScreenBuffer(houtpoint);
    }

     

    动态更新数值:

    主要代码:

    int key = 0;//计数器
    ……
    
    int main(){
        ……//这里的代码不变,和上面一样
    }
    
    void printPic(){
    	hop_flag = !hop_flag; 
    	if(!hop_flag){
    		houtpoint = hOutBuf;
    	}else{
    		houtpoint = hOutput;
    	}
    	
    	key++;
    	char score_char1[] = "Score:";
    	char score_char2[10];
    	itoa(key,score_char2,10);//将整型key转换成字符串,存入score_char2,10为十进制转换
    	strcat(score_char1,score_char2);//合并两个字符数组
    	
    	coord.Y = 1;
    	for(int i=0;i<20;i++){//这里循环只是为让大家能看出真的不闪屏
    		coord.Y++;
        	WriteConsoleOutputCharacter( houtpoint, score_char1, strlen(score_char1), coord, &bytes );
    	}	
    	SetConsoleActiveScreenBuffer(houtpoint);
    	
    }

     

     

     

    看了这么多我相信你们也可以使用C语言写出一个小游戏咯~

    在这也感谢其他博主的经验,希望大家一起加油~

    如有错误之处,虚心接受~

    🙂🙂🙂

    展开全文
  • 不多说,直接上Win32 VC++代码 ///FrameCPP.h /// #pragma once #include "resource.h" #include #include #include ...#pragma comment(lib, "comctl32.lib") #pragma comment(lib, "gdiplus.lib

    不多说,直接上Win32 VC++代码

    ///FrameCPP.h
    ///
    
    #pragma once
    
    #include "resource.h"
    #include <ShlObj.h>
    #include <CommCtrl.h>
    #include <vector>
    
    #include <comdef.h>
    #include <gdiplus.h>
    #pragma comment(lib, "comctl32.lib")  
    #pragma comment(lib, "gdiplus.lib")
    
    std::vector<WCHAR*> filenames;
    std::vector<Gdiplus::Image*> images;
    Gdiplus::Image* bgimg;
    int index;

    /// FramesCPP.cpp : 定义应用程序的入口点。
    ///
    
    #include "stdafx.h"
    #include "FramesCPP.h"
    
    #define MAX_LOADSTRING 100
    
    // 全局变量: 
    HINSTANCE hInst;                                // 当前实例
    WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
    WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
    
    // 此代码模块中包含的函数的前向声明: 
    ATOM                MyRegisterClass(HINSTANCE hInstance);
    BOOL                InitInstance(HINSTANCE, int);
    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                         _In_opt_ HINSTANCE hPrevInstance,
                         _In_ LPWSTR    lpCmdLine,
                         _In_ int       nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
    
        // TODO: 在此放置代码。
    
        // 初始化全局字符串
        LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadStringW(hInstance, IDC_FRAMESCPP, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
    
        // 执行应用程序初始化: 
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }
    
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_FRAMESCPP));
    
        MSG msg;
    	Gdiplus::GdiplusStartupInput gsi;
    	Gdiplus::GdiplusStartupOutput gso;
    	ULONG_PTR token;
    	GdiplusStartup(&token,&gsi,&gso);
    	bgimg = Gdiplus::Image::FromFile(L".\\bg.jpg");
        // 主消息循环: 
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    
        return (int) msg.wParam;
    }
    
    
    
    //
    //  函数: MyRegisterClass()
    //
    //  目的: 注册窗口类。
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex;
    
        wcex.cbSize = sizeof(WNDCLASSEX);
    
        wcex.style          = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = WndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = hInstance;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FRAMESCPP));
        wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_FRAMESCPP);
        wcex.lpszClassName  = szWindowClass;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
        return RegisterClassExW(&wcex);
    }
    
    //
    //   函数: InitInstance(HINSTANCE, int)
    //
    //   目的: 保存实例句柄并创建主窗口
    //
    //   注释: 
    //
    //        在此函数中,我们在全局变量中保存实例句柄并
    //        创建和显示主程序窗口。
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // 将实例句柄存储在全局变量中
    
       HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    //
    //  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  目的:    处理主窗口的消息。
    //
    //  WM_COMMAND  - 处理应用程序菜单
    //  WM_PAINT    - 绘制主窗口
    //  WM_DESTROY  - 发送退出消息并返回
    //
    //
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_COMMAND:
            {	
                int wmId = LOWORD(wParam);
                // 分析菜单选择: 
                switch (wmId)
                {
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
    			case IDM_OPEN:
    			{
    				LPITEMIDLIST pil = NULL;
    				INITCOMMONCONTROLSEX InitCtrls = { 0 };
    				TCHAR szBuf[4096] = { 0 };
    				BROWSEINFO bi = { 0 };
    				bi.hwndOwner = NULL;
    				bi.iImage = 0;
    				bi.lParam = NULL;
    				bi.lpfn = NULL;
    				bi.lpszTitle = _T("请选择文件路径");
    				bi.pszDisplayName = szBuf;
    				bi.ulFlags = BIF_BROWSEINCLUDEFILES;
    
    				InitCommonControlsEx(&InitCtrls);//在调用函数SHBrowseForFolder之前需要调用该函数初始化相关环境  
    				pil = SHBrowseForFolder(&bi);
    				for (int i = 0; i < filenames.size();i++)
    				{
    					delete filenames[i];
    					delete images[i];
    				}
    				filenames.clear();
    				images.clear();
    				KillTimer(hWnd, 1);
    				if (NULL != pil)//若函数执行成功,并且用户选择问件路径并点击确定  
    				{
    					SHGetPathFromIDList(pil, szBuf);//获取用户选择的文件路径  
    					WIN32_FIND_DATAW fd;
    					memset(&fd, 0, sizeof(fd));
    					TCHAR strall[MAX_PATH];
    					_tcscpy_s(strall, szBuf);
    					_tcscat_s(strall, _T("\\*.*"));
    					HANDLE findhandle = FindFirstFile(strall, &fd);
    					while (TRUE)
    					{
    						BOOL r = FindNextFile(findhandle, &fd);
    						TCHAR* filename = new TCHAR[260];
    						_tcscpy_s(filename,260, fd.cFileName);
    						TCHAR* filepath = new TCHAR[260];
    						_stprintf_s(filepath, 260, L"%s\\%s", szBuf, filename);
    						if (!r)
    							break;
    						if (_tcscmp(filename, L"..") != 0) {
    							filenames.push_back(filepath);
    							images.push_back(Gdiplus::Image::FromFile(filepath));
    						}
    					}
    					FindClose(findhandle);
    					SetTimer(hWnd, 1, 20, NULL);
    					//wprintf_s(_T("%s"), szBuf);
    				}
    				break;
    			}
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
                }
            }
            break;
    	case WM_ERASEBKGND:
    	{
    		//PAINTSTRUCT ps;
    		//HDC hdc = BeginPaint(hWnd, &ps);
    		 TODO: 在此处添加使用 hdc 的任何绘图代码...
    
    		if (filenames.size() > 0) {
    			Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(GetDC(hWnd));
    			Gdiplus::Image *tempimg = new Gdiplus::Bitmap(bgimg->GetWidth(), bgimg->GetHeight());
    			Gdiplus::Graphics* g1 = Gdiplus::Graphics::FromImage(tempimg);
    			//g->Clear(Gdiplus::Color::White);
    			g1->DrawImage(bgimg, 0, 0);
    			g1->DrawImage(images[index], 0, 0);
    			g1->Flush();
    			g1->Save();
    			g->DrawImage(tempimg, 0, 0);
    			tempimg->~Image();
    			g1->~Graphics();
    			g->~Graphics();
    		}
    		//EndPaint(hWnd, &ps);
    		break; 
    	}
    	case WM_TIMER:
    		{
    			index += 1;
    			if (index >= filenames.size())
    				index = 0;
    
    			RECT clientrect;
    			GetClientRect(hWnd, &clientrect);
    			InvalidateRect(hWnd, &clientrect, TRUE);
    			break;
    		}
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                //TODO: 在此处添加使用 hdc 的任何绘图代码...
                EndPaint(hWnd, &ps);
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    // “关于”框的消息处理程序。
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;
    
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
        }
        return (INT_PTR)FALSE;
    }
    


    展开全文
  • Bitmap bm = new Bitmap(this.pbTraffic.Image); BufferedGraphicsContext current = BufferedGraphicsManager.Current; BufferedGraphics buf = current.Allocate(pbTraffic....
  • CDC双缓冲闪屏绘图总结,很全面 如里需要绘多张图,并且有重叠的部份,当鼠标改变窗口大小时,重叠部份有严重的闪烁。非常难看
  • 最近在工作需要使用C#绘制图形,看了一下绘制的函数觉得很简单就开始着手工作了,但是在实际应用的时候发现鼠标进行绘制的时候会闪屏,原因是图元重绘的时间不一致,百度一下有很多更详细的,于是参照网上的解决办法...
  • 这个问题很影响人机交互的效果,最后通过一个大佬了解到了“双缓冲”技术,在大佬给的示例中我稍微修改了一下,现在分享给大家: 1、首先我重写了panel控件,项目(右键)–>添加新项–>自定义控件 2、添加...
  • 双缓冲技术解决屏幕刷新闪烁

    千次阅读 2016-12-03 16:13:30
    我们知道在我们电脑中,屏幕中显示的东西都会被放在一个称为显示缓存的地方,在通常情况下我们只有一个这样的缓冲区,也就是单缓冲,在单缓冲中任何绘图的过程都会被立即显示在屏幕中,而所谓双缓冲就是再这个显示的...
  • openGL ES双缓冲描画导致闪屏

    千次阅读 2018-08-13 11:48:50
    其实双缓冲,就是用来解决闪屏问题的。但存在这么一种情况,使得采用双缓冲描画会导致闪屏问题:一个进程(由于某些限制只能申请一个On- screen Surface)中,需要在两个不同的位置,同时显示不同的内容。 这种情况...
  • VS2012 GDI绘图双缓冲闪屏问题

    千次阅读 2017-10-19 14:01:40
    VS2012 GDI绘图双缓冲闪屏问题 CMemDC类 使用CMemDC类实现双缓冲是非常简单的 CDC *pDC = GetDC(); CMemDC dcMem(*pDC,this); CDC& dc = dcMem.GetDC(); HDC hdc = dc.m_hDC; using ...
  • C语言 双缓冲控制台防闪屏技术

    千次阅读 2018-11-29 21:24:09
    有,那就是我们在游戏绘图时用到吐的双缓冲技术,原理见下图   说简单也简单   1. 将要输出的数据写在缓冲区一(写的过程中显示的是缓冲区二的内容)   2.显示缓冲区一的内容   3.将要输出的数据写在...
  • 双缓冲解决切换图片闪屏实例双缓冲解决切换图片闪屏实例
  • 双缓冲设计消除绘图闪屏,C++,双缓冲设计消除绘图闪屏
  • 会动的花仙子 鼠标点击一次就出现一个花仙子而且随机移动(解决闪屏 双缓冲
  • 用GDI绘制四叶草,每秒中换一种随机颜色。重绘时候利用后台缓冲技术解决图像闪屏现象。纯WIN32API,没有利用MFC。
  • //在原来的基础上加上这些代码,剩下的按照原来的做,就可以解决闪屏问题 @Override public void update(Graphics src) { if(iBuffer==null) { iBuffer=createImage(this.getSize().width,this.get
  •  //开启双缓冲  SetStyle(ControlStyles.UserPaint, true);  SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.  SetStyle(ControlStyles.DoubleBuffer, true);  g = Graphics....
  • 一、闪屏的原因: 在用java绘图或者添加图片的时候会出现闪屏的现象,而绘图和添加图片都是要在原来的画布上重画得到的,因此闪屏也跟重画有一定的关系。正是这种先用背景色覆盖组件再重绘图像的方式导致了闪烁。...
  • 今天用 canvas 做 H5 的时候遇到了闪屏问题。闪烁效果如下图:   问题简介 功能简介 H5 该部分的功能为:通过点击二级菜单,切换图片的遮罩或者更换背景。 因为功能简单,所以用了原生 canvas 实现这个功能。但在...
  • 网上很多文章都是在重复下面这个代码块,对于这个代码段没啥好说的,关键在于一个细节:在你重写update的时候是否把super.update()去掉了,我们重写update方法就是为了全面接管,所以去掉super.update(),问题解决!...
  • MFC双缓冲 防止闪屏

    2012-04-15 13:39:00
    今天帮别人看改个闪屏的问题。 弄了挺久的。。写在把解决的方法写出来。 void CWanggeView::OnDraw(CDC* pDC) { CWanggeDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native ...
  • 双缓冲解决重绘和闪屏问题 重绘导致原因:UpdateData、Invalidate、InvalidateRect和UpdateWindow函数。 1. UpdateData重绘控件函数  UpdateData(TRUE)——刷新控件的值到对应的变量。(外部输入值交给内部...
  • 双缓冲闪屏的问题

    千次阅读 2011-08-04 21:16:46
    以上是双缓冲的绘图过程,但是还是不够的,要阻止背景的不断刷新: BOOL CSHANPingDlg::OnEraseBkgnd(CDC* pDC) {  // TODO: Add your message handler code here and/or call default  return true;//...
  • 因为计算机的计算速度很快,所以在画面较小的情况下我不会觉得有闪屏或不流畅的体验。 但一旦要刷新的画面较大,是会闪瞎开发者的眼的! 比如下面这段代码 int main() { while(1){ for(int i=1;i<=50;i++) { ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 947
精华内容 378
关键字:

双缓冲解决闪屏