GDI学习(2)

位图绘制

四部曲:
*加载位图,从文件中加载位图
*建立兼容DC,建立一个与窗口设备环境DC兼容的内存设备环境DC
*选用位图对象,内存DC使用步骤一中所建立的位图图像
*进行贴图,将内存DC内的内容贴到窗口DC中

1。加载位图
 LoadImage()函数,不仅可以加载位图,还可以加载图标,光标等图像资源。
HANDLE WINAPI LoadImage(
  _In_opt_ HINSTANCE hinst,    //句柄,包含被加载图像模型的实例句柄,若从硬盘文件或资源文件中加载,这个参数为NULL
  _In_     LPCTSTR   lpszName, //名称 ,被加载的资源所在的路径与文件名或资源名称
  _In_     UINT      uType,           //加载的类型  
                                                           *IMAGE_BITMAP:加载图像为位图文件,扩展名为:.bmp
                                                           *IMAGE_CUSOR 加载的图像为光标文件,扩展名:.cur
                                                           *IMAGE_ICON 加载的图像为图标文件,扩展名:.ico
  _In_     int       cxDesired,         //指定存储的宽度
  _In_     int       cyDesired,         //指定存储的高度
  _In_     UINT      fuLoad           //加载的方式   若从文件中加载 设置为LR_LOADFROMFILE
);



2,建立兼容DC

我们需要创建一个和设备兼容的内存设备环境,才有暂时放位图的地方
把位图对象用SelectObject函数选入到内存设备环境中,然后用贴图函数,把内存设备环境中的内容贴到设备环境中(DC)
内存DC在这里起到中转站的作用,暂时存储加载好的位图,最终我们会把内存DC上的贴图转到真正的DC上,所以内存DC和窗口DC要无缝衔接,也就是兼容。
在GDI中,用GreateCompatible()来建立内存DC

HDC GreateCompatible(需要与内存DC兼容的DC句柄),如果添的句柄为NULL,那么会创建一个与运用程序使用的当前显示器兼容的内存设备上下文环境跟窗口DC(HDC)一样,内存DC也要进行释放,所调用函数DeleteDC() BOOL DeleteDC(需要撤销的句柄)

3.选用位图对象

SelectObject()来实现,前面讲过,不再细讲。

4,进行贴图。

把内存DC内容复制到环境设备DC中,最常使用是BitBlt函数,其功能是从矩形框中复制一个位图到目标矩形
BOOL BitBlt(
  HDC hdcDest,     //目标设备环境句柄
  int nXDest,      //目的DC的X坐标
  int nYDest,      //目的DC的Y坐标 
  int nWidth,      //贴到目的DC的宽度
  int nHeight,     //贴到目的DC的高度
  HDC hdcSrc,      //源设备环境句柄
  int nXSrc,       //来源DC的X坐标
  int nYSrc,       //来源DC的Y坐标
  DWORD dwRop      //贴图方式 这里功能很多,能出很多效果。参数具体可查。直接拷贝:SRCCOPY

下面是实例:
#include


//-----------------------------------【库文件包含部分】---------------------------------------
// 描述:包含程序所依赖的库文件
//------------------------------------------------------------------------------------------------
#pragma comment(lib,"winmm.lib")  //调用PlaySound函数所需库文件


//定义宏
#define WINDOW_WIDTH 1137 //为窗口宽度定义的宏,以方便在此处修改窗口宽度
#define WINDOW_HEIGHT 640 //为窗口高度定义的宏,以方便在此处修改窗口高度
#define WINDOW_TITLE L"为梦想而战"


//全局变量声明
HDC g_hdc = NULL, g_mdc = NULL;       //全局设备环境句柄
HBITMAP    g_hBitmap = NULL;                 //定义一个位图句柄


//全局函数声明
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);//窗口过程函数
BOOL Game_Init(HWND hwnd); //在此函数中进行资源的初始化
VOID Game_Paint(HWND hwnd); //在此函数中进行绘图代码的书写
BOOL Game_CleanUp(HWND hwnd); //在此函数中进行资源的清理


//WinMain 函数 ,我们的程序从这里开始
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//【1】窗口创建四步曲之一:开始设计一个完整的窗口类
WNDCLASSEX wndClass = { 0 }; //用WINDCLASSEX定义了一个窗口类
wndClass.cbSize = sizeof(WNDCLASSEX);        //设置结构体的字节数大小
wndClass.style = CS_HREDRAW | CS_VREDRAW;            //设置窗口的样式
wndClass.lpfnWndProc = WndProc;        //设置指向窗口过程函数的指针
wndClass.cbClsExtra = 0; //窗口类的附加内存,取0就可以了
wndClass.cbWndExtra = 0;    //窗口的附加内存,依然取0就行了
wndClass.hInstance = hInstance;    //指定包含窗口过程的程序的实例句柄。
wndClass.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);  //本地加载自定义ico图标
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);         //指定窗口类的光标句柄。
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  //为hbrBackground成员指定一个白色画刷句柄
wndClass.lpszMenuName = NULL;    //用一个以空终止的字符串,指定菜单资源的名字。
wndClass.lpszClassName = L"ForTheDreamOfGameDevelop";   //用一个以空终止的字符串,指定窗口类的名字。


//【2】窗口创建四步曲之二:注册窗口类
if (!RegisterClassEx(&wndClass)) //设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口
return -1;


//【3】窗口创建四步曲之三:正式创建窗口
HWND hwnd = CreateWindow(L"ForTheDreamOfGameDevelop", WINDOW_TITLE, //喜闻乐见的创建窗口函数CreateWindow
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);


//【4】窗口创建四步曲之四:窗口的移动、显示与更新
MoveWindow(hwnd, 200, 20, WINDOW_WIDTH, WINDOW_HEIGHT, true); //调整窗口显示时的位置,使窗口左上角位于(200,20)处
ShowWindow(hwnd, nShowCmd);                                        //调用ShowWindow函数来显示窗口
UpdateWindow(hwnd);                          //对窗口进行更新,就像我们买了新房子要装修一样


//游戏资源的初始化,若初始化失败,弹出一个消息框,并返回FALSE
if (!Game_Init(hwnd))
{
MessageBox(hwnd, L"资源初始化失败", L"消息窗口", 0);            //使用MessageBox函数,创建一个消息窗口
return FALSE;
}
PlaySound(L"注册机音乐-BRD - Teleport Pro kg.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP); //循环播放背景音乐 


//【5】消息循环过程
MSG msg = { 0 };                  //定义并初始化msg
while (msg.message != WM_QUIT)              //使用while循环,如果消息不是WM_QUIT消息,就继续循环
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))    //查看应用程序消息队列,有消息时将队列中的消息派发出去。
{
TranslateMessage(&msg);              //将虚拟键消息转换为字符消息
DispatchMessage(&msg);          //分发一个消息给窗口程序。
}
}


//【6】窗口类的注销
UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance);  //程序准备结束,注销窗口类
return 0;
}


//-----------------------------------【WndProc( )函数】--------------------------------------
// 描述:窗口过程函数WndProc,对窗口消息进行处理
//------------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT paintStruct; //定义一个PAINTSTRUCT结构体来记录一些绘制信息


switch (message) //switch语句开始
{
case WM_PAINT: // 若是客户区重绘消息
g_hdc = BeginPaint(hwnd, &paintStruct);  //指定窗口进行绘图工作的准备,并用将和绘图有关的信息填充到paintStruct结构体中。
Game_Paint(hwnd);
EndPaint(hwnd, &paintStruct); //EndPaint函数标记指定窗口的绘画过程结束
ValidateRect(hwnd, NULL); // 更新客户区的显示
break; //跳出该switch语句


case WM_KEYDOWN: // 若是键盘按下消息
if (wParam == VK_ESCAPE)    // 如果被按下的键是ESC
DestroyWindow(hwnd); // 销毁窗口, 并发送一条WM_DESTROY消息
break; //跳出该switch语句


case WM_DESTROY: //若是窗口销毁消息
Game_CleanUp(hwnd); //调用自定义的资源清理函数Game_CleanUp()进行退出前的资源清理
PostQuitMessage(0); //向系统表明有个线程有终止请求。用来响应WM_DESTROY消息
break; //跳出该switch语句


default: //若上述case条件都不符合,则执行该default语句
return DefWindowProc(hwnd, message, wParam, lParam); //调用缺省的窗口过程
}


return 0; //正常退出
}


//-----------------------------------【Game_Init( )函数】--------------------------------------
// 描述:初始化函数,进行一些简单的初始化
//------------------------------------------------------------------------------------------------
BOOL Game_Init(HWND hwnd)
{
g_hdc = GetDC(hwnd);  //获取设备环境句柄


//-----【位图绘制四步曲之一:加载位图】-----
g_hBitmap = (HBITMAP)LoadImage(NULL, L"11.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE);   //加载位图


//-----【位图绘制四步曲之二:建立兼容DC】-----
g_mdc = CreateCompatibleDC(g_hdc);    //建立兼容设备环境的内存DC


Game_Paint(hwnd);
ReleaseDC(hwnd, g_hdc);  //释放设备环境
return TRUE;
}


//-----------------------------------【Game_Paint( )函数】--------------------------------------
// 描述:绘制函数,在此函数中进行绘制操作
//--------------------------------------------------------------------------------------------------
VOID Game_Paint(HWND hwnd)
{
//-----【位图绘制四步曲之三:选用位图对象 】-----
SelectObject(g_mdc, g_hBitmap);    //将位图对象选入到g_mdc内存DC中
//-----【位图绘制四步曲之四:进行贴图】-----
BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY);    //采用BitBlt函数贴图,参数设置为窗口大小  
}


//-----------------------------------【Game_CleanUp( )函数】--------------------------------
// 描述:资源清理函数,在此函数中进行程序退出前资源的清理工作
//---------------------------------------------------------------------------------------------------
BOOL Game_CleanUp(HWND hwnd)
{
//释放资源对象
DeleteObject(g_hBitmap);
DeleteDC(g_mdc);
return TRUE;
}


这里的音乐我换了个MP3格式的,放不出来,现在用的是.wav格式 GDI学习(2)_第1张图片

你可能感兴趣的:(windows编程)