佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

楼主: tensaix2j

分享我做的sprite, 另加游戏制作过程。

[复制链接]
 楼主| 发表于 11-12-2007 10:06 AM | 显示全部楼层
#include "windows.h"
int WINAPI WinMain(HINSTANCE h,HINSTANCE hPrev, LPSTR lp,int winMode)
{
    return 0;
}

楼上那个main
跟我们 一开始学 C 的 main
int main ( int argc , char *argv[])

的不同,就是
(注意看哦)。。

1. 他有个, winapi 在 winmain 前面,

这个据说是 有关 stdcall 的东西。。我也不是很懂。 只是读过,
这个 stdcall 是说, 这个function 本身会自己负责 清理 自己的 stack
而不是 caller 负责 。。  Function 的variable 都是 load 在 stack memory 。。
function 完毕,那些 在stack memory 里 的 local variable 都要清理

FYI 就好了。。。暂时不重要。。

接下来 有 四个 arguments

第一个
hInstance: handle to the instance, 就是 pointer to 这个 application instance

第二个, handle to previous instance.. 也不清楚什么情形下会用到。

第三个, 就是 command line argument 啦。 也就是我们平时用的 argv (只是这个是 一个 string, 平时我们用的 argv 是 array of string )

第四个,我也不清楚。抱歉啦。
回复

使用道具 举报


ADVERTISEMENT

发表于 11-12-2007 12:07 PM | 显示全部楼层
根据Microsoft的Win32 SDK Help档案,

int WINAPI WinMain(

    HINSTANCE hInstance,        // handle to current instance
    HINSTANCE hPrevInstance,        // handle to previous instance
    LPSTR lpCmdLine,        // pointer to command line
    int nCmdShow         // show state of window
   );

在这里,第四个argument被称为 nCmdShow 其作用是决定该Application的视窗的显示方式:

nCmdShow

Specifies how the window is to be shown. This parameter can be one of the following values:

Value        Meaning
SW_HIDE        Hides the window and activates another window.
SW_MINIMIZE        Minimizes the specified window and activates the top-level window in the system's list.
SW_RESTORE        Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position (same as SW_SHOWNORMAL).
SW_SHOW        Activates a window and displays it in its current size and position.
SW_SHOWMAXIMIZED        Activates a window and displays it as a maximized window.
SW_SHOWMINIMIZED        Activates a window and displays it as an icon.
SW_SHOWMINNOACTIVE        Displays a window as an icon. The active window remains active.
SW_SHOWNA        Displays a window in its current state. The active window remains active.
SW_SHOWNOACTIVATE        Displays a window in its most recent size and position. The active window remains active.
SW_SHOWNORMAL        Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position (same as SW_RESTORE).


hPrevInstance 是用来侦察这个Application是否已经开启过,以防止使用者同时开启多个相同的Application。这个Argument已经没有实际的用处了,因为现在的Windows已经可以很好的处理multi-instancing。一般上这个Argument都是设定为NULL.

[ 本帖最后由 geekman 于 11-12-2007 12:14 PM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 11-12-2007 02:56 PM | 显示全部楼层
其实我是觉得蛮奇怪的。。。
这个时候我都还没开始 createWindow 它怎么知道是什么mode的。。。而且我可能create 两三个window
回复

使用道具 举报

发表于 11-12-2007 03:12 PM | 显示全部楼层
这点我也不是很清楚,我一路来都是用 Borland 的 C++ Builder, 都不需要烦恼 Windows Creation的问题的。不过 nCmdShow 是 Argument, 是由Calling Function(在这里一般是 Windows 本身)提供的,可能windows会自行判断决定要用什么 mode,或者只是提供一个数值,你在CreateWindow 要不要用这个数值由你决定。
回复

使用道具 举报

 楼主| 发表于 11-12-2007 06:40 PM | 显示全部楼层
好啦, 接下来。。。

我们来认识一下 这个

LRESULT CALLBACK msgHandler(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
       
}
回复

使用道具 举报

 楼主| 发表于 11-12-2007 06:43 PM | 显示全部楼层
LRESULT CALLBACK msgHandler(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
        
}

在还没 解释 这个function 之前, 或许我有必要 解释 一下 callback function 的概念。。。
在解释 什么是 callback function 之前呢, 又有必要 解释一下, 什么是 function pointer 。

function pointer 简单来说呢, 就是 pointer to a static function ( instance 的 method 另当别论)

就比如说 你有一个 function , 拿两 个 int 的 arguments
int f(int a,int b)
{
   
}

那你的 function pointer 可以这样declare

int (*fp)(int,int) ;   

然后这样 assign

fp = &f;

这个时候呢, 你就可以把, 整个 function 当成 variable 酱来用。。。。
也可以当成 argument, pass 进去 另一个 function

例如说呢。。。

int funcThatTakesFunc ( int a,int b , int (*c)(int,int) )
{
    c(a,b);
}

然后你就可以把整个 fp 丢进去。。。
例如:
funcThatTakesFunc( 2,3, fp);

[ 本帖最后由 tensaix2j 于 11-12-2007 07:09 PM 编辑 ]
回复

使用道具 举报

Follow Us
 楼主| 发表于 11-12-2007 07:30 PM | 显示全部楼层
window message 的 故事, 我们在继续谈。。。
回复

使用道具 举报

 楼主| 发表于 12-12-2007 09:26 AM | 显示全部楼层
LRESULT CALLBACK msgHandler(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
        
}

首先我们来看看这个function
这个 function 你 define 好后呢。。。

就可以 用 function pointer 的 方法 assign 它到 你的 window class 。。
     myWindowClass->lpfnWndProc = msgHandler;

然后再注册 RegisterClassEx(myWindowClass)

这个迟点再谈。。


它被呼唤的方法会是callback 式的。。 而且不是你呼唤,是 windows 一收到属于这个windows 的 msg ,它就会被呼唤。。


暂时不用担心 那个 LRESULT ,只是一个 long int 来的。。

重要的是 那四个 arguments:

HWND  hwnd 这是 handle to 你的window

UINT   msg  这是 主要的 message  (例如 ,什么button 被按, mouse click 等等。。。有很多很多种类的 msg)

WPARAM  wp   这是 additional parameters of 你的 msg , (例如, mouse  的 coordinate..)

LPARAM  lp   这也是 additional parameters of 你的 msg
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 12-12-2007 06:46 PM | 显示全部楼层
那么, 首先,

想好 什么 message 你要 handle 的。。

在 game 里面, 我们一定 会用到 keypress 还有 mouseclick

所以以下这些 msg 就先写个 handler 的 skeleton 吧 , 它的detail 自己去看 msdn

switch(msg)
    {
        case WM_KEYUP:    // 键被释放
                        break;
               
               
                case WM_CHAR:   // 键被按
                                                
                        break;
               
               
                case WM_CREATE:  //windows 被制造
                        
                        break;
                                
               
                case WM_TIMER:  // timer 啦
                                       
                        break;
               
               
                case WM_MOUSEMOVE:  //mouse 移动
                        break;

               
                case WM_RBUTTONUP: //mouse 右键被释放
                        break;   


                        
                case WM_LBUTTONUP: //mouse 左键被释放
               
                        break;   
               
               
                case WM_RBUTTONDOWN:   //mouse 右键被按下去
                        break;   
               
                                
                case WM_LBUTTONDOWN:  //mouse 左键被按下去
                        break;
                        
               
                case WM_CLOSE:   //windows 关掉
         
                        break;
                        
               
                case WM_DESTROY:   //windows 毁灭掉
                        PostQuitMessage(0);
                        break;
               
               
                default :       //其它不想处理的 msg..

                        return DefWindowProc(hwnd,msg,wp,lp);
        }
回复

使用道具 举报

 楼主| 发表于 17-12-2007 07:39 PM | 显示全部楼层
啊。。。说到哪里了。。。最近比较忙,所以很少上来。。。


接下来 就是
create 一个 window class 然后 register 一个 classname

首先 呢, 我们 declare 一个 window class 的 物件
WNDCLASSEX *wcl;

关于这个struct, 请参考
http://msdn2.microsoft.com/en-us/library/ms633577.aspx


然后。。

填饱 这个 struct,  

wcl->cbSize=sizeof(WNDCLASSEX);
wcl->hInstance= h;                               // application instance 的pointer
wcl->lpszClassName = className;      // 这个 classname 很重要。 它是 一个 string (lpctstr) 来的
wcl->lpfnWndProc = msgHandler;        // 这个是你的 message handler ,上面说了

其它的可以 顾名思义。 例如 icon 啦, cursor 啦。。。 这些是一定要填的。。

wcl->style = 0;
wcl->hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcl->hIconSm = NULL;
wcl->hCursor = LoadCursor(NULL, IDC_ARROW);
wcl->hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wcl->cbClsExtra = 0;
wcl->cbWndExtra = 0;
wcl->lpszMenuName = NULL;



最后, register 一下

RegisterClassEx(wcl)



然后 就可以 用 createWindow 了。。因为这个function 的其中一个 param 便是 classname
register 好了的 classname 才可以用。

http://msdn2.microsoft.com/en-us/library/ms632679.aspx


char className[128]        =    “myClassname";
char windowCaption[256]    =    "My simple shooting game";

HWND hwndMain;

hwndMain = CreateWindow(className,                                         
                            windowCaption,                                    
                            WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,     
                            CW_USEDEFAULT ,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            NULL,
                            NULL,
                            h ,
                            NULL);

[ 本帖最后由 tensaix2j 于 17-12-2007 08:03 PM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 17-12-2007 07:45 PM | 显示全部楼层
这个时候, 你应该会有如下 的 代码。。。 (可以参考对照下)


#include "windows.h"
#include <stdio.h>

LRESULT CALLBACK msgHandler(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{

        switch(msg)
    {
        case WM_KEYUP:
                        break;
               
               
                case WM_CHAR:
                        break;
               
               
               
                case WM_CREATE:
                        break;
                        
               
               
                case WM_TIMER:
                        break;
               
               
                case WM_MOUSEMOVE:
                        break;

               
                case WM_RBUTTONUP:
                        break;   


                        
                case WM_LBUTTONUP:
                        break;   
               
               
                case WM_RBUTTONDOWN:
                        break;   
               
                                
                case WM_LBUTTONDOWN:
                        break;
                        
               
                case WM_DESTROY:
                        PostQuitMessage(0);
                        break;
               
                default :
                        return DefWindowProc(hwnd,msg,wp,lp);
        }
        return 0;
        
}



// --------------A function to register window class-----------------------------
int registerWindowClass(WNDCLASSEX *wcl, char *className, HINSTANCE h)
{
        wcl->cbSize=sizeof(WNDCLASSEX);
        wcl->hInstance= h;
        wcl->lpszClassName = className;
        wcl->lpfnWndProc = msgHandler;
        wcl->style = 0;
        wcl->hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wcl->hIconSm = NULL;
        wcl->hCursor = LoadCursor(NULL, IDC_ARROW);
        wcl->hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wcl->cbClsExtra = 0;
        wcl->cbWndExtra = 0;
        wcl->lpszMenuName = NULL;
        
        if (!RegisterClassEx(wcl))  //If class registered unsuccessful
        {
                return -1;
        }
        return 0;
}


int WINAPI WinMain(HINSTANCE h,HINSTANCE hPrev, LPSTR lp,int winMode)
{
        HWND hwndMain;
        MSG msg;
        WNDCLASSEX wcl;
        
        char *className               =        "My Window";
        char *windowCaption        =        "My game (v 1.0.0)";
        
        
        if (registerWindowClass(&wcl,className, h))
        {
                fprintf(stderr, "Error in registering class");
                return 0;
        }        
        
        
        
        hwndMain = CreateWindow(        className,                                                                                 
                                                        windowCaption,                                                                        
                                                        WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,         
                                                        CW_USEDEFAULT ,
                                                        CW_USEDEFAULT,
                                                        CW_USEDEFAULT,
                                                        CW_USEDEFAULT,
                                                        NULL,
                                                        NULL,
                                                        h ,
                                                        NULL);
        
        ShowWindow(hwndMain, winMode);
        UpdateWindow(hwndMain);
        
        //Main Loop
        while(GetMessage(&msg,NULL,0,0)>0)
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
        
        return 0;
}

[ 本帖最后由 tensaix2j 于 17-12-2007 07:46 PM 编辑 ]
回复

使用道具 举报

发表于 18-12-2007 01:58 PM | 显示全部楼层
楼主,可以PM我你的代码吗?
很想多了解这方面的构造。。

谢谢分享
回复

使用道具 举报

 楼主| 发表于 18-12-2007 06:42 PM | 显示全部楼层
PM 你了。 。。。。。。。。
回复

使用道具 举报

发表于 18-12-2007 09:00 PM | 显示全部楼层
好强!根据你的方法, 我刚刚做了我人生第一个c的win32 程式。其实做c的win32 程式是我以前的愿望,因为我学的第一个programming 就是 C programming.
回复

使用道具 举报

 楼主| 发表于 19-12-2007 09:07 AM | 显示全部楼层
谢谢, 你们的回帖是我发帖的动力。
回复

使用道具 举报

 楼主| 发表于 19-12-2007 09:12 AM | 显示全部楼层
接下来,关于这个 main loop
//Main Loop
while(GetMessage(&msg,NULL,0,0)>0)
{
          TranslateMessage(&msg);
           DispatchMessage(&msg);
}

一般上 我们的C 程序, 跑完后就结束了



所以上面那个 msg loop, 是说 program 会一直不停 的打探有什么msg,
getMessage 是blocking 的。 没message 的话,它会等到有
若有的话,它就进入那个loop body,呼唤 DispatchMessage, 接下来 就会然那个 被你收藏在 wndclass 的 callback function 被呼唤
这样 program 就不会结束, 直到 wmdestroy 这个 msg 被收到,然后在你handle这个东西那里quit


你们自己去 了解 一下 ,是很straight forward 可以明白的
给你们一个 link
http://www.winprog.org/tutorial/message_loop.html


其实, 现在 你不一定要知道 所有的 东西,
例如 里面有很多 或许是 新手们第一次看到的 hWnd, hInstance
UINT message, lresult, callback, wndClass,

but at minimum,
要知道 Entry point 是 WinMain, 然后 msg handling 是那个 callback function 就可以

至少 当你想做 某些东西 的时候, 知道 要从哪里 着手。。

[ 本帖最后由 tensaix2j 于 19-12-2007 09:14 AM 编辑 ]
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 19-12-2007 09:17 AM | 显示全部楼层
上面的东西 慢慢digest一下,

接下来 我们 来聊聊

HDC
回复

使用道具 举报

 楼主| 发表于 19-12-2007 06:46 PM | 显示全部楼层
在 我还没进入 HDC 这个 topic,

你们可以尝试 compile 上面 那段 代码 。。。

首先把它save 起来 。  example:  yourgame.c

然后, 去你的 command line , (或用 notepad++ 的人, 可以按 f5, 打 cmd)
在 lcc ,compile的指令是

lcc yourgame.c

这个时候呢, 一个 yourgame.obj 的物件就会被产生。
基本上compile 只是 把该代码 从 text 变成 binary 。。。

你要制造的 。exe 还必须 做 linking 。
linking 的意思是, 把所有 相关的 .obj,还有libraies 都link 起来 ,
而且,有两种Link法,一种是static,一种是 dynamic...
这个 我迟点在说。。。


它的指令是
lcclnk yourgame.obj

完成后, 你的
yourgame.exe  就出炉了

这时 你应该完成了 第一个空白的 windows.

就出来了。
回复

使用道具 举报

 楼主| 发表于 19-12-2007 07:03 PM | 显示全部楼层
HDC, Handle to Device Context

http://www.toymaker.info/Games/html/gdi.html

简单来讲, 是给你画画的地方。。


这时, 你或许会问, 为何 要create 那个 windows 呢?

基本上, create 一个 window 的目的, 就是 让你有 个地方 去画游戏的画面。。

你可 不要 打那个 default的 console window 的主意哦。。虽然你也可以抓它的 hwnd 然后 拿它的 HDC 。。

例如
        HWND myHandle;
        SetConsoleTitle("aaa");
        myHandle= FindWindow( NULL, "aaa");
        HDC hdc = GetDC(myHandle);

但老实讲我个人觉得那个 黑漆漆的 console window 本来就 不是 part of 你的 program
而是 windows 借你用 来 display  stdout 还有 stderr 的东西.
所以不鼓励乱用。

还有, 若不create 一个 window 来做 画面,也可以直接 抓desktop的 HDC
例如
    HDC hDC = GetDC(NULL);

应该有人看过 那种 windowless的 卡通, 在 desktop 跑来跑去的东西吧。。。

[ 本帖最后由 tensaix2j 于 19-12-2007 07:06 PM 编辑 ]
回复

使用道具 举报

发表于 21-12-2007 11:43 AM | 显示全部楼层
好复杂。。, 学习中。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 25-12-2025 10:30 AM , Processed in 0.128018 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表