美文网首页
Windows程序设计-创建窗口

Windows程序设计-创建窗口

作者: 故事观察日记 | 来源:发表于2020-04-20 20:48 被阅读0次

学完了汇编和C语言,想做个小游戏,需要编写带窗口界面的程序,所以接下来学习一些WIndows编程的知识。参考书籍为《Windows程序设计 第五版》,由于教材比较老,一些内容可能已经过时。
C语言中,入门程序是:

#include <stdio.h>
int main()
{
    printf("hello, world\n");
    return 0;
}

Windows对应程序为:

#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    MessageBox(NULL, TEXT("Hello, Windows 98!"), TEXT("HelloMsg"), 0);
    return 0;
}

头文件windows.h是一个最重要的包含文件,里面包含了另外几个最重要且最基本的头文件:

WINDEF.H       基本数据类型定义。
WINNT.H        支持Unicode的类型定义。
WINBASE.H      内核函数。
WINUSER.H      用户界面函数。
WINGDI.H       图形设备接口函数。

WINAPI标志符定义在WINDEF.H中:

#define WINAPI _stdcall

_stdcall是一种函数调用约定,约定了参数传递顺序等调用细节。之前学习的C语言函数代码都是使用的默认调用约定,所以省略了。在stdio.h等文件内可以看到大量带有调用约定的函数声明。
WinMain的第一个参数一般叫做“实例句柄”(Instance Handle),它唯一标识了这个程序。第二个参数已不使用,通常总是NULL(定义为0)。
第三个参数是PSTR类型,它与LPSTR都定义在WINNT.H中,如下:

typedef char CHAR;
typedef CHAR *PCHAR,*LPCH,*PCH,*NPSTR,*LPSTR,*PSTR;

指针运算符*是自右向左结合,所以PSTRLPSTR都被定义为指向字符串的指针,等同于:

typedef CHAR* LPSTR;
typedef CHAR* PSTR;

前缀LP是长指针(Long Pointer)的缩写,STR是字符串(String)的缩写。
WinMain的第三个参数是用来运行程序的命令行(Command Line),有些Windows程序在启动时用它来把文件装入内存。第四个参数用来指明程序最初如何显示:正常显示或最大化最小化。
MessageBox函数是用来显示段信息的。它的第一个参数通常是一个窗口句柄。第二个参数就是要显示的文本字符串。第三个参数是标题。第四个参数是以前缀MB_打头的一些常量的组合,用来表示在对话框里希望有哪种按钮,0代表只显示OK按钮。这些常量定义在WINUSER.H中:

#define MB_OK 0
#define MB_ABORTRETRYIGNORE 2
#define MB_APPLMODAL 0
#define MB_DEFBUTTON1 0
#define MB_OKCANCEL 1
#define MB_RETRYCANCEL 5
#define MB_YESNO 4
#define MB_YESNOCANCEL 3
...还有几十个

第二和第三个参数的字符串都被包在TEXT宏代码里,TEXTWINNT.H中定义如下:

#ifdef UNICODE
#define __TEXT(q) L##q
#else
#define __TEXT(q) q
#endif
#define TEXT(q) __TEXT(q) 

##是连接两段的内容,也就是说,如果定义了UNICODETEXT()括号中的字符串会被替换为L字符串(如"HelloMsg"会变成L"HelloMsg");如果没定义UNICODE,那TEXT()不起效果,括号中的字符串维持原样。
一般来说不需要把所有字符串都打包到TEXT宏代码里,这样做是为了把程序转换成Unicode时会方便很多。
若这个Windows程序命名为HelloMsg.c,可以执行如下命令对其编译:

gcc HelloMsg.c -o HelloMsg.exe

执行结果:

HelloMsg
MessageBox函数创建的这个用来提示信息的消息框小窗口,灵活性有限,下面用CreateWindow函数创建自己的窗口,代码如下:
/*hellowin.c -- 在窗口客户区显示“Start Game”*/

#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("HelloWin");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    
    if (!RegisterClass(&wndclass)){
        MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
        return 0;
    }
    
    hwnd = CreateWindow(szAppName,
                        //TEXT("The Hello Program"),
                        TEXT("Snake"),
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);
                        
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    
    while(GetMessage(&msg,NULL,0,0)){
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;  
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    
    switch(message){
        case WM_CREATE:
            //PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
            return 0;
        
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            GetClientRect(hwnd, &rect);
            DrawText(hdc, TEXT("Start Game"), -1, &rect, 
                    DT_SINGLELINE | DT_CENTER | DT_VCENTER);
            EndPaint(hwnd, &ps);
            return 0;
        
        case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

这段代码中有两个函数,一个是入口函数WinMain,另一个是窗口过程函数WndProc。代码大多是创建窗口的一些初始化信息,后面会慢慢熟悉,这里不再详细分析。
编译执行后效果:

创建窗口
由于创建窗口的代码大多都是固定的,所以可以将它们封装一下,比如放在新建的myWindow.h中,这样代码就可以简化成:
#include <windows.h>
#include <myWindows.h>

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    myCreateWindow(hInstance, hPrevInstance, szCmdLine, iCmdShow);
}

好了,一个新的窗口创建完成了,接下来要向窗口中添加内容,完成一个贪吃蛇的小游戏。

相关文章

  • Windows程序设计-创建窗口

    学完了汇编和C语言,想做个小游戏,需要编写带窗口界面的程序,所以接下来学习一些WIndows编程的知识。参考书籍为...

  • WNDCLASS 结构

    WNDCLASS 结构 Windows 的窗口总是基于窗口类来创建的,窗口类同时确定了处理窗口消息的窗口过程(回调...

  • 创建D3D窗口

    D3D创建(一) 从Windows普通窗口到D3D窗口在windows中,几乎所有程序都要依赖于窗口。今天就分析如...

  • Windows程序设计-输出文本

    这一篇的目标是实现在上一篇创建的窗口中添加一些文本。对应《Windows程序设计》第四章。1.绘制和重绘的概念一些...

  • 为nzModal增加可拖拽功能 最后是RxJS实现版

    实现功能很简单,就是nzModal像windows里的窗口一样,可以拖拽窗口以移动窗口位置。 思路也很简单。创建一...

  • electron 让无框窗口像原生窗口一样可调节大小

    如果不想被系统的窗口影响界面,特别是Windows的窗口栏那么丑。。所以用electron 创建一个无框窗口是非常...

  • 使用Dx11渲染纹理1——初始化

    新建Windows窗口工程 使用VS2019工程创建一个默认的窗口工程。 创建交换链和设备及上下文 添加头文件和依...

  • window

    Tumbling Windows 翻滚窗口 Sliding Windows 滑动窗口

  • 《每天进步一点点》DAY1:常用DOS命令

    打开DOS窗口 windows(徽标)+ r ->cmd ->回车 常用命令 d: 切换盘符 md 创建新...

  • 挂载windows共享

    1.在windows磁盘里创建一个共享文件; win键+R 快捷键(运行窗口弹出) 命令窗口设置口令 删除用户 ...

网友评论

      本文标题:Windows程序设计-创建窗口

      本文链接:https://www.haomeiwen.com/subject/zmljihtx.html