WIN32界面开发之一:初试加载背景界面
来源:互联网 发布:freebsd内核源码 编辑:程序博客网 时间:2024/05/22 06:33
前言:在实际开发中,虽然有已经成形的界面库DUILIB,但DUILIB无法加载异形窗体,对PNG图片的支持不到位,最终我下决心,自己开发一套界面库,利用GDI+完成2D和3D功能,在这里,我将要记录下,我所做的界面开发的过程,并将它们整理成博客分享给大家,一步步来学习吧。
内容概要:这篇主要实现的功能是加载一个背景界面,向大家介绍下,如何用GDI+加载背景界面的问题,然后就是如何在指定位置托动窗体。
一、创建WIN32工程
1、因为是GDI+绘图,所以对于GDI+的初始化是必须的,在stdafx.h里加入下面代码:
#include <gdiplus.h>#pragma comment(lib,"gdiplus.lib");using namespace Gdiplus;2、首先看一下WINMAIN函数的写法:
ULONG_PTR gdiplusToken = 0;int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){Gdiplus::GdiplusStartupInput gdiplusStartupInput;Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);Register(WindowProc,hInstance,L"transparent");HWND hwnd=Create(L"transparent",L"TEST",hInstance);Display(hwnd);Message();Gdiplus::GdiplusShutdown(gdiplusToken);return 0;}讲解:
1、首先是GDI+的初始化;
2、注册窗口类(Register函数)
3、创建窗口(Create函数)
4、显示窗口(Display函数)
5、消息循环(Message函数)
6、关闭GDI+应用,释放资源
3、注册窗口类(Register函数)写法
BOOL Register(WNDPROC fWndProc,HINSTANCE hInstance,LPCTSTR szClassName){WNDCLASSEX wce={0};wce.cbSize=sizeof(wce);wce.style=CS_HREDRAW|CS_VREDRAW;wce.lpfnWndProc=fWndProc;wce.cbClsExtra=0;wce.cbWndExtra=0;wce.hInstance=hInstance;wce.hIcon=NULL;wce.hCursor=LoadCursor(NULL,IDC_ARROW);wce.hbrBackground=(HBRUSH)(6);wce.lpszMenuName=NULL;wce.lpszClassName=szClassName;wce.hIconSm=NULL;ATOM nAtom=RegisterClassEx(&wce);if(nAtom==0) return false;return true;}讲解:注册窗口类也没什么好讲的,就是注册WNDCLASSEX结构体,首先对其各项进行赋值,然后调用RegisterClassEx()对其注册,但这里注意的两个地方,fWndPorc是传进来的消息处理函数的指针,我们就是在这个函数里截获窗体有关的各种消息,然后对其进行处理。szClassName是要注册窗体的类名;不同的窗口类,类名不能相同;
4、WndProc消息处理函数的写法;
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam){switch(uMsg){case WM_DESTROY:PostQuitMessage(100);break;case WM_CREATE:{LONG styleValue = ::GetWindowLong(hwnd, GWL_STYLE);styleValue &= ~WS_CAPTION;styleValue &= ~WS_MAXIMIZEBOX; styleValue &= ~WS_MINIMIZEBOX; styleValue &= ~WS_THICKFRAME; styleValue &= ~WS_BORDER; styleValue &= ~WS_CAPTION;::SetWindowLong(hwnd, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);}break;case WM_PAINT:break;case WM_LBUTTONDOWN:break;}return DefWindowProc(hwnd,uMsg,wParam,lParam);}5、创建窗体(Create函数)写法
HWND Create(LPCTSTR lpClassName,LPCTSTR lpWindowName,HINSTANCE hInstance){HWND m_hWnd = ::CreateWindowEx(WS_EX_LAYERED, L"transparent", _T(""),WS_POPUPWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, (HINSTANCE)::GetModuleHandle(NULL), 0);if(m_hWnd == NULL || !::IsWindow(m_hWnd))return NULL;return m_hWnd;}6、显示窗体(Display函数)
void Display(HWND hwnd){ShowWindow(hwnd,SW_SHOWNORMAL);UpdateWindow(hwnd);}7、消息循环(Message()函数)
void Message(){MSG msg={0};while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}}
二、背景绘图
1、添加消息响应,在WM_PAINT消息中,添加消息响应SetBackground(hwnd,L"C:\\bg.png");
case WM_PAINT:SetBackground(hwnd,L"C:\\bg.png");break;2、SetBackground函数实现
void SetBackground(HWND m_hWnd,const TCHAR* pBackImgFullPath){//加载图片Gdiplus::Image* pImage = Gdiplus::Image::FromFile(pBackImgFullPath);if (pImage==NULL){assert(false && _T("背景图片打开失败!"));}RECT windowRect;GetWindowRect(m_hWnd,&windowRect);SIZE sizeWindow;if (windowRect.left==windowRect.right){sizeWindow.cx=pImage->GetWidth();sizeWindow.cy=pImage->GetHeight();}else{sizeWindow.cx=windowRect.right-windowRect.left;sizeWindow.cy=windowRect.bottom-windowRect.top;}HDC hDC = ::GetDC(m_hWnd);HDC hdcMemory = CreateCompatibleDC(hDC);RECT rcWindow;GetWindowRect(m_hWnd,&rcWindow);BITMAPINFOHEADER stBmpInfoHeader = { 0 }; int nBytesPerLine = ((sizeWindow.cx * 32 + 31) & (~31)) >> 3;stBmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER); stBmpInfoHeader.biWidth = sizeWindow.cx; stBmpInfoHeader.biHeight = sizeWindow.cy; stBmpInfoHeader.biPlanes = 1; stBmpInfoHeader.biBitCount = 32; stBmpInfoHeader.biCompression = BI_RGB; stBmpInfoHeader.biClrUsed = 0; stBmpInfoHeader.biSizeImage = nBytesPerLine * sizeWindow.cy; PVOID pvBits = NULL; HBITMAP hbmpMem = ::CreateDIBSection(NULL, (PBITMAPINFO)&stBmpInfoHeader, DIB_RGB_COLORS, &pvBits, NULL, 0);assert(hbmpMem != NULL);HGDIOBJ hbmpOld = ::SelectObject( hdcMemory, hbmpMem);POINT ptWinPos = { rcWindow.left, rcWindow.top };Gdiplus::Graphics graph(hdcMemory);graph.SetSmoothingMode(Gdiplus::SmoothingModeNone);graph.DrawImage(pImage, 0, 0, sizeWindow.cx, sizeWindow.cy);graph.FillRectangle(&SolidBrush(Color::Gray),0,0,100,50); //用GDI+在画布上画图HMODULE hFuncInst = LoadLibrary(_T("User32.DLL"));typedef BOOL (WINAPI *MYFUNC)(HWND, HDC, POINT*, SIZE*, HDC, POINT*, COLORREF, BLENDFUNCTION*, DWORD); MYFUNC UpdateLayeredWindow;UpdateLayeredWindow = (MYFUNC)::GetProcAddress(hFuncInst, "UpdateLayeredWindow");POINT ptSrc = { 0, 0};BLENDFUNCTION blendFunc;blendFunc.BlendOp = 0;blendFunc.BlendFlags = 0;blendFunc.AlphaFormat = 1;blendFunc.SourceConstantAlpha = 255;//AC_SRC_ALPHA//不会发送 WM_SIZE和WM_MOVE消息if(!UpdateLayeredWindow(m_hWnd, hDC, &ptWinPos, &sizeWindow, hdcMemory, &ptSrc, 0, &blendFunc, ULW_ALPHA)){assert(L"UpdateLayeredWindow 调用失败");TCHAR tmp[255] = {_T('\0')};}delete pImage;graph.ReleaseHDC(hdcMemory);::SelectObject( hdcMemory, hbmpOld); ::DeleteObject(hFuncInst);::DeleteObject(hbmpOld);::DeleteObject(hbmpMem); ::DeleteDC(hdcMemory);::DeleteDC(hDC);}讲解:两个关键部分注意一下:
1、
BITMAPINFOHEADER stBmpInfoHeader = { 0 }; int nBytesPerLine = ((sizeWindow.cx * 32 + 31) & (~31)) >> 3;stBmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER); stBmpInfoHeader.biWidth = sizeWindow.cx; stBmpInfoHeader.biHeight = sizeWindow.cy; stBmpInfoHeader.biPlanes = 1; stBmpInfoHeader.biBitCount = 32; stBmpInfoHeader.biCompression = BI_RGB; stBmpInfoHeader.biClrUsed = 0; stBmpInfoHeader.biSizeImage = nBytesPerLine * sizeWindow.cy; PVOID pvBits = NULL; HBITMAP hbmpMem = ::CreateDIBSection(NULL, (PBITMAPINFO)&stBmpInfoHeader, DIB_RGB_COLORS, &pvBits, NULL, 0);这是创建一个32位的位图,这部分代码必须有,否则会出现问题,我们的绘图就是在这个位图上画,然后再显示的桌面上;
2、
HMODULE hFuncInst = LoadLibrary(_T("User32.DLL"));typedef BOOL (WINAPI *MYFUNC)(HWND, HDC, POINT*, SIZE*, HDC, POINT*, COLORREF, BLENDFUNCTION*, DWORD); MYFUNC UpdateLayeredWindow;UpdateLayeredWindow = (MYFUNC)::GetProcAddress(hFuncInst, "UpdateLayeredWindow");POINT ptSrc = { 0, 0};BLENDFUNCTION blendFunc;blendFunc.BlendOp = 0;blendFunc.BlendFlags = 0;blendFunc.AlphaFormat = 1;blendFunc.SourceConstantAlpha = 255;//AC_SRC_ALPHA//不会发送 WM_SIZE和WM_MOVE消息if(!UpdateLayeredWindow(m_hWnd, hDC, &ptWinPos, &sizeWindow, hdcMemory, &ptSrc, 0, &blendFunc, ULW_ALPHA)){assert(L"UpdateLayeredWindow 调用失败");TCHAR tmp[255] = {_T('\0')};}讲解:这是UpdateLayeredWindow的标准写法,UpdateLayeredWindow支持ALPHA通道,所以支持PNG图片的显示,但需要注意的是UpdateLayeredWindow不会发送WM_PAINT消息,所以我们要在WM_CREATE消息中,添加一行
PostMessageW(hwnd,WM_PAINT,NULL,NULL);最终的效果:
三、移动窗体
对于移动窗体就比较简单了,主要是发送SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);消息,我们这里是只要在窗体上鼠标按下,就发送这个消息,所以在WM_LBUTTONDOWN消息中添加响应即可,代码如下:
case WM_LBUTTONDOWN:SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);break;至此,这篇的实现就全部讲完了,与往常一样,代码地址:http://download.csdn.net/detail/harvic880925/5757093
转载的标明出处哦!地址:http://blog.csdn.net/harvic880925/article/details/9331701
- WIN32界面开发之一:初试加载背景界面
- MFC之一改变界面背景
- win32界面
- win32界面
- Android开发---加载h5界面
- Win32 应用界面构造
- WIN32 SDK界面编程
- WIN32界面开发之三:DUI雏形开发(一)
- WIN32界面开发之三:DUI雏形开发(二)
- WIN32界面开发之三:DUI雏形开发(一)
- WIN32界面开发之三:DUI雏形开发(二)
- WIN32界面开发之DUI雏形开发(一)
- WIN32界面开发之DUI雏形开发(二)
- JAVA GUI 开发---登录界面加载背景图片
- JAVA GUI 开发---登录界面加载背景图片
- iOS开发 动态加载广告界面
- 通话界面背景
- WIN32界面开发之二:GDI+中的局部刷新技术
- 中央政府释放重大利好 2015年信息消费将超3万亿
- GitHub使用
- SAP中的一些名詞解釋
- 【语言-批处理】 添加项到注册表
- TCP 连接的建立和终止
- WIN32界面开发之一:初试加载背景界面
- 【语言-批处理】删除注册表中的项
- objdump的使用
- Git常用操作命令
- Linux 2.6中断下半部机制分析
- C++ map的基本操作和使用
- 两台服务器之间的自动备份
- 协议(Protocol)的用法和代码例子 有demo
- Java内存泄露的理解与解决