windows sdk编程系列文章22 ---- 启动画面.doc_第1页
windows sdk编程系列文章22 ---- 启动画面.doc_第2页
windows sdk编程系列文章22 ---- 启动画面.doc_第3页
windows sdk编程系列文章22 ---- 启动画面.doc_第4页
windows sdk编程系列文章22 ---- 启动画面.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

windows sdk编程系列文章 - 启动画面2008-04-23 23:27上一章我们学习了位图的使用.在这一章我们要用 上帝赋予我们的创造力来融会贯通上一章我们学到的知识.那就是研究如何用位图来创建启动画面. 理论: 首先,我们先要搞清楚什么是启动画面.举个简单的例子:我们启动某些作 的专业一点的程序时(比如Netscape,Adobe Acrobat等)会先跳出一个启动画面.上面通常有一 些版权信息,版本号等.与此同时,程序后台正做着一些程序的加载或初始化工作.这个启动画面有别于 一般的窗口.它没有标题栏,没有系统菜单,也没有边框.只有一张位图在屏幕上显示一会儿,然后消失 .在这一章我们来试试自己做一个. 第一步你可能会想到把要显示的位图包含到资源文件中去.但是这样做 有一个缺点.你的程序只在启动的时候显示这张位图,可是它却至始至终存在于你的内存中,直到你 把程序关掉.这不能不说是对内存的极大浪费.好办法是:创建一个资源DLL(动态连接库)来包含位图 和它独特的显示代码.这样,你就可以在想显示启动画面的时候加载他,用完了就卸载它.所以,我们的 程序需要2个模块:主程序和启动画面DLL.我们要把位图放到这个DLL的资源中去. 基本步骤如下: 1. 把位图作为一个位图资源放到DLL中去. 2. 主程序调用 LoadLibrary 把 dll 加载到内存中去. 3. DLL 被调用后,它会建立一个定时器用于管理启动画面显示的时间.然后,注册并创建一个没有 标题和边框的窗口.同时在窗口的客户区显示位图. 4. 等启动画面的显示时间长度到达你预先的设定值,启动画面消失,控制权回到主程序手中. 5. 主程序调用 FreeLibrary 从内存中卸载 DLL .然后,做它该做的事去. 下面我们来研究细节部分 加载/卸载 DLL你可以用 LoadLibrary 灵活的加载一个 DLL ,它的格式如下: HMODULE LoadLibrary( LPCTSTR lpFileName ); 它只有一个参数: 你想要加载的 DLL 的名称所在的地址.调用成功返回指向该DLL模块的句柄,反之返回NULL. 要卸载 DLL, 则调用 FreeLibrary: BOOL FreeLibrary( HMODULE hModule ); 它也只有一个参数: 你想要卸载的 DLL 模块的句柄(通常就是上面那个函数返回的啦). 怎样使用定时器首先, 你要用 SetTimer 创建一个定时器: UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc ); hWnd接受这个定时器消息的窗口的句柄.如果,你的定时器不需要窗口接受它的消息,你也可以 用NULL作为参数nIDEvent 定时器的 ID 值. 由你自己定义. uElapse 定时器定的时间.以ms(千分之一秒)为单位. lpTimerFunc 处理该定时器消息的函数所在的地址.如果你用NULL作为该参数,那么定时器的消息会被送给 hWnd 参数所指定的窗口.SetTimer 如果成功则返回定时器的 ID 否则返回 NULL. 所以最好不要把定时器的ID设为0你可以用2种方法创建定时器: 如果你有一个窗口并且定时器把消息传给这个窗口.那么你需要把所有的4个参数都传送给 Settimer 函数 (lpTimerFunc参数必须为NULL). 如果你没有窗口或者你不想让窗口处理定时器的消息,那么你必须在窗口句柄中传送一个NULL.同时你要指定 用于处理定时器消息的函数的地址. 在这个例子中我们要使用第一种方法. 当你设定的时间到了, 与定时器相连的窗口会收到 WM_TIMER 消息.例如,你指定 uElapse 的值为 1000, 你的窗口每 过一秒都会收到 WM_TIMER 消息.等到你再也不需要这个定时器了,就用 KillTimer 来去除定时器. BOOL KillTimer( HWND hWnd, UINT_PTR uIDEvent );例子: 见光盘FirstWindow24;- ; 主程序 ;- #include windows.h#include tchar.hTCHAR ClassName = _T(SplashDemoClass);TCHAR Libname = _T(Splash.dll);TCHAR AppName = _T(Splash Screen Example);LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) switch(uMsg) case WM_DESTROY: PostQuitMessage(NULL); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); return 0;int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) WNDCLASSEX wc; MSG msg; HWND hWnd; HMODULE hMod = LoadLibrary(Libname); if(hMod) FreeLibrary(hMod); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = NULL; wc.cbWndExtra = NULL; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszClassName = ClassName; wc.lpszMenuName = NULL; wc.hIcon = wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL,IDC_ARROW); RegisterClassEx(&wc); hWnd = CreateWindowEx(NULL,ClassName,AppName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL); ShowWindow(hWnd,SW_SHOWNORMAL); while(GetMessage(&msg,NULL,0,0) TranslateMessage(&msg); DispatchMessage(&msg); return msg.wParam; ;- ; 位图 DLL ;- #include windows.h#include tchar.hTCHAR BitmapName = _T(MySplashBMP);TCHAR ClassName = _T(SplashWndClass);HBITMAP hBitmap;DWORD TimerID;HINSTANCE g_hInstance;LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) PAINTSTRUCT ps; HDC hdc; HDC hMemoryDC; HBITMAP hOldBmp; BITMAP bitmap; DWORD DlgHeight; DWORD DlgWidth; RECT DlgRect; RECT DesktopRect; switch(uMsg) case WM_DESTROY: if(hBitmap) DeleteObject(hBitmap); PostQuitMessage(NULL); break; case WM_CREATE: GetWindowRect(hwnd,&DlgRect); GetWindowRect(GetDesktopWindow(),&DesktopRect); DlgHeight = DlgRect.bottom - DlgRect.top; DlgWidth = DlgRect.right - DlgRect.left; MoveWindow(hwnd,(DesktopRect.right - DlgWidth)/2,(DesktopRect.bottom - DlgHeight)/2,DlgWidth,DlgHeight,FALSE); hBitmap = LoadBitmap(g_hInstance,BitmapName); TimerID = SetTimer(hwnd,1,2000,NULL); break; case WM_LBUTTONDOWN: DestroyWindow(hwnd); break; case WM_PAINT: hdc = BeginPaint(hwnd,&ps); hMemoryDC = CreateCompatibleDC(hdc); hOldBmp = (HBITMAP)SelectObject(hMemoryDC,hBitmap); GetObject(hBitmap,sizeof(BITMAP),&bitmap); StretchBlt(hdc,0,0,250,250,hMemoryDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); SelectObject(hMemoryDC,hOldBmp); DeleteDC(hMemoryDC); EndPaint(hwnd,&ps); break; case WM_TIMER: SendMessage(hwnd,WM_LBUTTONDOWN,NULL,NULL); KillTimer(hwnd,TimerID); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); return 0;DWORD ShowBitMap() WNDCLASSEX wc; MSG msg; HWND hWnd; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = NULL; wc.cbWndExtra = NULL; wc.hInstance = g_hInstance; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = ClassName; wc.hIcon = wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL,IDC_ARROW); RegisterClassEx(&wc); hWnd = CreateWindowEx(NULL,ClassName,NULL,WS_POPUP,CW_USEDEFAULT,CW_USEDEFAULT, 250,250,NULL,NULL,g_hInstance,NULL); ShowWindow(hWnd,SW_SHOWNORMAL); while(GetMessage(&msg,NULL,0,0) TranslateMessage(&msg); DispatchMessage(&msg); return msg.wParam; BOOL WINAPI DllMain( HINSTANCE hModule, DWORD dwReason, LPVOID lpvReserved ) if(dwReason = DLL_PROCESS_ATTACH) g_hInstance = hModule; ShowBitMap(); return TRUE;分析:我们首先要再主程序中检验这段代码. HMODULE hMod = LoadLibrary(Libname); if(hMod) FreeLibrary(hMod);我们调用 LoadLibrary 读入名称为 splash.dll 的 DLL. 然后, 用 FreeLibrary 卸载. 一直到 DLL 完成初始化, LoadLibrary才会返回. 主程序的任务到此为止. 更有趣的部分再 DLL里. if(dwReason = DLL_PROCESS_ATTACH) g_hInstance = hModule; ShowBitMap(); DLL 被加载后, Windows 调用它的有 DLL_PROCESS_ATTACH 标记的入口函数. 我们借这个机会显示启动画面. 首先,我们 保存 DLL 事例的句柄以供将来使用. 然后, 调用一个叫 ShowBitMap 的函数进行真正的工作. ShowBitMap 注册一个窗口, 创建这个窗口和显示它.就像我们以前创建窗口一样. 有趣的是这个 CreateWindowEx 调用: hWnd = CreateWindowEx(NULL,ClassName,NULL,WS_POPUP,CW_USEDEFAULT,CW_USEDEFAULT, 250,250,NULL,NULL,g_hInstance,NULL);注意, 这里的窗口风格仅仅使用了 WS_POPUP . 所以窗口即没有标题栏,也没有边界. 我们同时也限定窗口的宽高为 250x250个像素.现在窗口创建好了. 在 WM_CREATE 的消息处理代码里我们把这个窗口移到屏幕的中央.代码如下: case WM_CREATE: GetWindowRect(hwnd,&DlgRect); GetWindowRect(GetDesktopWindow(),&DesktopRect); DlgHeight = DlgRect.bottom - DlgRect.top; DlgWidth = DlgRect.right - DlgRect.left; MoveWindow(hwnd,(DesktopRect.right - DlgWidth)/2,(DesktopRect.bottom - DlgHeight)/2,DlgWidth,DlgHeight,FALSE); 它先找到桌面和窗口的大小. 然后,计算出一个窗口左上角的坐标. 使这个窗口能位于屏幕中央. hBitmap = LoadBitmap(g_hInstance,BitmapName); TimerID = SetTimer(hwnd,1,2000,NULL); break; 下一步,它用 LoadBitmap 从资源中读入位图并且创建一个定时器.定时器的 ID 为 1 时间间隔为 2 秒. 定时器 将每 2 秒 向窗口发送 WM_TIMER 消息. case WM_PAINT: hdc = BeginPaint(hwnd,&ps); hMemoryDC = CreateCompatibleDC(hdc); hOldBmp = (HBITMAP)SelectObject(hMemoryDC,hBitmap); GetObject(hBitmap,sizeof(BITMAP),&bitmap); StretchBlt(hdc,0,0,250,250,hMemoryDC,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); SelectObject(hMemoryDC,hOldBmp); DeleteDC(hMemoryDC); EndPaint(hwnd,&ps); break; 当窗口收到 WM_PAINT 消息, 它创建一个内存DC( 在wi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论