版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net/10km/article/details/84951442
minigui框架提供了窗口双缓冲区机制,利用这个机制可以实现窗口显示特效。不是所有的窗口都可以利用双缓冲区实现显示特效,窗口需要具备WS_EX_AUTOSECONDARYDC
扩展窗口风格。所以下面的函数中首先就是判断窗口是否有WS_EX_AUTOSECONDARYDC
扩展窗口风格。
使用miniStudio设计UI时要将SecondaryDC
属性置为true
,就设置了窗口的WS_EX_AUTOSECONDARYDC
扩展窗口风格,如下图:
下面的screen_pull
函数就是利用双缓冲区机制实现了窗口打开时从右到左推拉的显示效果。
#include <unistd.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <mgncs/mgncs.h>
#include "resource.h"
#include "ncs-windows.h"
// 获取窗口hWnd矩形坐标并转为基于屏幕的坐标
static PRECT fl_get_screen_rect(HWND hWnd, PRECT prect)
{
GetWindowRect(hWnd,prect);
HWND parent = GetParent(hWnd);
WindowToScreen(parent,&prect->left,&prect->top);
WindowToScreen(parent,&prect->right,&prect->bottom);
return prect;
}
/**
* 窗口水平向左推入,hwnd需要WS_EX_AUTOSECONDARYDC窗口风格
*/
static void screen_pull (HWND hwnd)
{
// 只对双缓冲区窗口有效
if(!(GetWindowExStyle(hwnd) & WS_EX_AUTOSECONDARYDC))
return;
MSG msg;
HDC sec_dc;
/* 这里通过设置ON_UPDSECDC_DONOTHING,
* 禁止ShowWindow函数将新窗口内容输出到屏幕,而只是画到SecondaryDC
* 再在后面的循环中将SecondaryDC中的内容一步一步画到屏幕DC.
*/
sec_dc = GetSecondaryDC (hwnd);
SetSecondaryDC (hwnd, sec_dc, ON_UPDSECDC_DONOTHING);
/* get the content of the active main window */
ShowWindow (hwnd, SW_SHOWNORMAL);
/* wait for MSG_IDLE */
while (GetMessage (&msg, hwnd)) {
if (msg.message == MSG_IDLE)
break;
DispatchMessage (&msg);
}
RECT scr_rect;
fl_get_screen_rect(hwnd,&scr_rect);
RECT win_rect;
GetWindowRect(hwnd,&win_rect);
int w = scr_rect.right -scr_rect.left;
int h = scr_rect.bottom-scr_rect.top;
/* 直接输出到屏幕DC,实现从从右向左推拉显示,间隔100毫秒 */
for(int shift=0;shift <= w;shift+=20)
{
BitBlt (sec_dc, 0, 0, shift, h,
HDC_SCREEN, scr_rect.right - shift, 0, 0);
usleep (100000);
}
/* 函数结束时要恢SecondaryDC的默认更新方式:ON_UPDSECDC_DEFAULT */
SetSecondaryDC (hwnd, sec_dc, ON_UPDSECDC_DEFAULT);
}
下面是参照MGNCS的ncsCreateModalDialogFromID
函数写的调用示例,在执行doModal
函数前调用screen_pull
函数实现推拉特效 :
int myCreateModalDialogFromID (HPACKAGE package, Uint32 dlgId,
HWND owner,
NCS_EVENT_HANDLER_INFO* handlers,
DWORD user_data)
{
int ret = 0;
mDialogBox * dialog = SAFE_CAST(mDialogBox,
ncsCreateMainWindowIndirectFromID(package,dlgId,owner,(HICON)0,(HMENU)0,handlers,user_data));
if (dialog) {
screen_pull(dialog->hwnd);
ret = _c(dialog)->doModal(dialog, TRUE);
if(IsMainWindow(dialog->hwnd)){
MainWindowThreadCleanup(dialog->hwnd);
}
}
return ret;
}
关于窗口双缓冲区的官方示例代码,参见 minigui示例代码库(http://www.minigui.org/downloads/mg-samples-3.0.12.tar.gz)中的mg-samples-3.0.12/dbuff
文件夹