📄 move pic.cpp
字号:
/*==========================================================
Move Pic.cpp -- A move-picture game with SDK
Soft Zealot (R) Robin Hood, 2001
SoftZealot@china.com Soft_Zealot@china.com
====================================================
我正在学习SDK编程,尝试编写了一个小游戏,因为我讨厌
一些无聊的编程问题,我喜欢有意思的编程工作 :)
这个游戏完全是用SDK编写的,没有涉及MFC,其中打开图片
的函数是Charles Petzold的《Windows程序设计》一书中的
源代码,我只不过加上了注释,看懂了意思而已。其他的代
码是我自己编写的,你可以任意使用其中的代码。
欢迎大家和我讨论编程的问题,你可以在www.csdn.net的专
家门诊的vc部分找到我,我的id是Soft_Zealot或者
SoftZealot, :),不好意思,水平不够只好多注册几个。
如果你发现了bug或者找到了任何能够改进程序性能或者任何
能够使code更精炼的方法,请你通知我,我会很高兴能够更
加完善这个游戏。
====================================================
有待完成:
1.胜利时通知游戏者游戏时间
3.可不可以找到寻找最佳解的算法
4.如何加入预览功能,可不可以采用类似Splash方法
====================================================
bugs :
1.显示图片后每个Static控件排列不整齐
2.由于对图像处理和windows底层工作原理还不是很清楚,所
以有可能会有内存泄漏
==========================================================*/
#include <windows.h>
#include <commdlg.h>
#include <time.h>
#include "Move Pic.h"
#include "resource.h"
/*==========================================================
应用程序入口函数
==========================================================*/
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szMenuName[] = TEXT ("MainMenu") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
// save the application's HINSTANCE
hInst = hInstance ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ; // WndProc !!! here
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, "AppIcon") ; // how to load self-cus icon
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH) ;
wndclass.lpszMenuName = szMenuName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
// Caculate the window's size and position, I don't like huge_window :-)
int cxWindow, cyWindow;
cxWindow = GetSystemMetrics (SM_CXSCREEN) / 3;
cyWindow = GetSystemMetrics (SM_CYSCREEN) / 3;
hwnd = CreateWindow (szAppName, // window class name
TEXT ("奇幻拼图 Soft Zealot"), // window caption
WS_OVERLAPPEDWINDOW, // window style
cxWindow, // initial x position
cyWindow, // initial y position
cxWindow, // initial x size
cyWindow, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
// message WM_QUIT cause function GetMessage return 0
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
/*==========================================================
窗口函数
==========================================================*/
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HMENU hMenu ;
static HWND hwndPic_Button[4][4] ;
static int iStcPos[4][4], iStcPosSave[4][4] ;
static HBITMAP hBitmap, hBmpStc ;
static int cxClient, cyClient ;
static int i, j ;
static int idStcClk, idStcBlank ;
static OPENFILENAME ofn ;
static bool bWinFlag ;
BITMAP bitmap ;
HDC hdc, hdcMem, hdcStc ;
PAINTSTRUCT ps ;
RECT rcClient, rcWin ;
int iStcClkPos, iStcBlankPos ;
int cxScr, cyScr ;
float fcxDiv, fcyDiv, fDiv ;
switch (message)
{
case WM_CREATE:
InitOfnStruct (ofn, hwnd) ;
// create statics who hold pic
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
hwndPic_Button[i][j] =
CreateWindow (TEXT ("Static"), NULL,
WS_CHILD | WS_VISIBLE | SS_NOTIFY | SS_BITMAP | SS_SUNKEN,
0, 0, 0, 0,
hwnd, (HMENU) (4 * i + j), hInst, NULL) ;
iStcPos[i][j] = 4 * i + j ;
}
// 使static控件不能接收mouse点击消息
bWinFlag = true ;
// 开始使reset菜单无效
hMenu = GetMenu (hwnd) ;
EnableMenuItem (hMenu, IDM_GAME_RESET, MF_GRAYED) ;
return 0 ;
case WM_SIZE:
// get client area size
cxClient = LOWORD (lParam);
cyClient = HIWORD (lParam);
// move the statics to the new center
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
MoveWindow (hwndPic_Button[i][j],
(iStcPos[i][j] % 4) * cxClient / 4,
(iStcPos[i][j] / 4) * cyClient / 4,
cxClient / 4, cyClient / 4, TRUE);
}
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
EndPaint (hwnd, &ps) ;
return 0 ;
// 处理菜单命令
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_GAME_RESET:
/*==================================================
游戏复位:因为Static已经加载图像,窗口也得到调整,所
以我们需要打开图像时,每个Static的位置,在这里恢复
Static的位置就行了。如果以后加入计时功能,就需要复位
开始时间。
==================================================*/
// 恢复初始Static位置信息
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
iStcPos[i][j] = iStcPosSave[i][j] ;
// 移动Static控件回到初始位置
MoveWindow (hwndPic_Button[i][j],
(iStcPos[i][j] % 4) * cxClient / 4,
(iStcPos[i][j] / 4) * cyClient / 4,
cxClient / 4, cyClient / 4, TRUE);
}
bWinFlag = false ;
return 0 ;
case IDM_PIC_OPEN:
// 显示打开文件对话框
if (!GetOpenFileName (&ofn))
return 0 ;
// 如果已经有一个DIB,删除它
if (hBitmap)
{
DeleteObject (hBitmap) ;
hBitmap = NULL ;
}
// 从DIB创建DDB
SetCursor (LoadCursor (NULL, IDC_WAIT)) ; // 使用漏斗指针
ShowCursor (TRUE) ;
hdc = GetDC (hwnd) ;
hBitmap = CreateBitmapObjectFromDibFile (hdc, szFileName) ;
ReleaseDC (hwnd, hdc) ;
ShowCursor (FALSE) ;
SetCursor (LoadCursor (NULL, IDC_ARROW)) ; // 恢复箭头指针
// 使客户区无效以便稍后重绘
InvalidateRect (hwnd, NULL, TRUE) ;
if (hBitmap == NULL)
{
// 如果不能载入DIB文件,显示错误消息
MessageBox (hwnd, TEXT ("Cannot load DIB file"),
szAppName, MB_OK | MB_ICONEXCLAMATION) ;
}
else
{
/*==================================================
在调整窗口大小之前随机安排Static控件的位置,以便调整
窗口的时候也随机产生了Static的布局。注意分割后的图像
仍然是按照顺序(id)分配给Static的,随机的只是位置。
==================================================*/
srand ( (unsigned int) time (NULL)); // for random seed
int iRanA, iRanB ;
for (i = 0; i < 32; i++)
{
// 得到 0 -- 16 之间的两个随机数
iRanA = rand( ) % 16 ;
do
{
iRanB = rand( ) % 16 ;
}
while (iRanA == iRanB);
// 随机调整 Note: index = id XXX[index] = pos
iStcBlankPos = iStcPos[iRanA / 4][iRanA % 4] ;
iStcPos[iRanA / 4][iRanA % 4] = iStcPos[iRanB / 4][iRanB % 4] ;
iStcPos[iRanB / 4][iRanB % 4] = iStcBlankPos ;
}
// 保存开始状态
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
iStcPosSave[i][j] = iStcPos[i][j] ;
MoveWindow (hwndPic_Button[i][j],
(iStcPos[i][j] % 4) * cxClient / 4,
(iStcPos[i][j] / 4) * cyClient / 4,
cxClient / 4, cyClient / 4, TRUE);
}
/*==================================================
调整窗口大小以适应图像
==================================================*/
GetWindowRect (hwnd, &rcWin);
GetClientRect (hwnd, &rcClient);
GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -