运用Windows API进行编程

运用Windows API进行编程

运行Windows应用程序在桌面显示Windows窗口。窗口内背景色为灰色,且窗口中居中显示“大家好,这是我的第一个Windows API程序!”同时播放背景音乐,并可通过程序改变窗口显示风格为只有标题栏,以及鼠标指针形状为手型。

实验环境

vs2022


窗口创建基本流程

1、注册窗口类,指定窗口类的名称和窗口回调函数
RegisterClassEx函数 : 注册一个扩展的窗口类,这个窗口类可以创建多个窗口实例
2、创建窗口,指定注册窗口类,窗口标题,窗口的大小
CreateWindow函数 : 创建窗口实例
3、显示窗口
ShowWindow函数:设置指定窗口的显示状态
4、开始消息循环
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);//转换消息
DispatchMessage(&msg);//消息分发
}
While退出,线程结束,否则循环的过程中系统自动回调窗口过程函数
5、窗口函数中处理窗口消息
WindowProc回调函数(窗口过程函数):处理窗口接收的消息,switch函数根据接收的消息的类别分类处理,如果都不符合,则调用DefWindowProc默认处理

基本代码流程

1、头文件和库

#include<Windows.h>
#include<mmsystem.h>
#include<tchar.h>
#include"resource.h"
#pragma comment(lib, "winmm.lib") // 链接winmm库  

#include<tchar.h>的宏“_T”:
_T支持 Unicode 和 ANSI 字符串的兼容性。根据项目的字符集设置,_T 宏会展开为 L 前缀(表示宽字符字符串)或普通字符字面量(表示 ANSI 字符串)。这意味着如果修改项目的编码模式我们不需要修改所有的字符串字面量。

2、全局变量和函数

HINSTANCE hInst;//存储实例句柄的全局变量
HWND hwnd;//窗口句柄的全局变量

ATOM MyRegisterClass(HINSTANCE hInstance);//注册窗口类
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);//创建和显示窗口
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);//窗口函数中处理窗口消息

3、入口主函数

int WINAPI WinMain(_In_ HINSTANCE hInstance, 
    _In_opt_ HINSTANCE hPrevInstance, 
    _In_ LPSTR lpCmdLine,
    _In_ int nCmdShow)
{
    
    //1、注册窗口类
    if (!MyRegisterClass(hInstance))
    {
        MessageBox(NULL, _T("窗口类注册失败!"), _T("错误"), MB_OK | MB_ICONERROR);
        return FALSE;
    }

    //2、创建窗口;3、显示窗口
    if (!InitInstance(hInstance, nCmdShow))
    {
        MessageBox(NULL, _T("窗口创建失败!"), _T("错误"), MB_OK | MB_ICONERROR);
        return FALSE;
    }
    // 循环播放背景音乐
    PlaySound(_T("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC| SND_LOOP);
    
    
    //4、开始消息循环
    MSG msg;//消息

    while (GetMessage(&msg, (HWND)NULL, 0, 0))//从消息队列里取消息到msg
    {
        TranslateMessage(&msg);//翻译消息(鼠标、键盘之类的消息)
        DispatchMessage(&msg);//转发消息到5、窗口过程
    }

    return (int)msg.wParam;
}

4、注册窗口类函数

//注册窗口类
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    
    /*
    窗口类
    typedef struct WNDCLASSEX {
    UINT        cbSize;             //结构体大小
     //Win 3.x
    UINT        style;              //窗口风格
    WNDPROC     lpfnWndProc;        //窗口过程函数指针
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;          //当前实例句柄
    HICON       hIcon;              //大图标
    HCURSOR     hCursor;            //鼠标
    HBRUSH      hbrBackground;      //背景
    LPCSTR      lpszMenuName;       //菜单
    LPCSTR      lpszClassName;      //窗口类名称指针,创建窗口时需要使用
     //Win 4.0
    HICON       hIconSm;            //小图标
    }
    */
    WNDCLASSEX wcx;
    wcx.cbSize = sizeof(wcx);
    wcx.style = CS_HREDRAW | CS_VREDRAW;//窗口在发生水平或垂直方向上的变化时,重画窗口
    wcx.lpfnWndProc = MainWndProc;
    wcx.cbClsExtra = 0;
    wcx.cbWndExtra = 0;
    wcx.hInstance = hInstance;
    wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcx.hCursor = LoadCursor(NULL, IDC_HAND);//手型鼠标
    //wcx.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);//改成灰色背景
    wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wcx.lpszMenuName = NULL;//没有菜单
    wcx.lpszClassName =_T("MainWClass");
    wcx.hIconSm = (HICON)LoadImage(hInstance,
        MAKEINTRESOURCE(5), IMAGE_ICON,
        GetSystemMetrics(SM_CXSMICON),//标准小图标的宽度
        GetSystemMetrics(SM_CYSMICON),//标准小图标的高度
        LR_DEFAULTCOLOR);
    /*
    if (!RegisterClassEx(&wcx))
    {
        return 1;
    }*/
    return RegisterClassEx(&wcx);
}

5、创建和显示窗口函数

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    
/*
HWND CreateWindowExW(
 DWORD dwExStyle,
 LPCWSTR lpClassName,        //窗口类名称 wcx.lpszClassName
 LPCWSTR lpWindowName,       //窗口标题
 DWORD dwStyle,              //窗口样式
 int X,
 int Y,
 int nWidth,
 int nHeight,
 HWND hWndParent,           //父窗口
 HMENU hMenu,               //菜单
 HINSTANCE hInstance,       //当前实例句柄
 LPVOID lpParam);
*/
    hInst = hInstance;//存储实例句柄在全局变量
    hwnd = CreateWindow(_T("MainWClass"),
        _T("hello"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,//默认
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        (HWND)NULL,
        (HMENU)NULL,//没有菜单
        hInstance,
        (LPVOID)NULL);

    if (!hwnd)
    {
        return FALSE;
    }
    
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);//立即显示

    return TRUE;
}

6、窗口过程函数

//窗口过程函数:处理窗口接收的消息
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        //关闭窗口
    case WM_DESTROY:        
        PostQuitMessage(0);
        break;
        //通知窗口需要重绘
    case WM_PAINT: {
         //存储绘画操作的信息。
        PAINTSTRUCT ps;
        //调用BeginPaint函数,它为窗口准备一个设备上下文(HDC),用于绘画。函数将绘画信息存储在ps中,并返回设备上下文的句柄。
        HDC hdc = BeginPaint(hwnd, &ps);

        // 设置文本背景为透明 如果创建窗口类时已经设定窗口背景色为灰色,则只要令文本背景为灰色即可。
        //SetBkMode(hdc, TRANSPARENT); 
        // 设置文本背景色
        SetBkColor(hdc, RGB(200, 200, 200));
        // 清除窗口背景
        ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &ps.rcPaint, NULL, 0, NULL);//ETO_OPAQUE标志表示用背景色填充矩形区域。

        //文本输出
        const TCHAR* text = _T("大家好,这是我的第一个Windows API程序!");
        int length = _tcslen(text);
        // 设置文本颜色
        SetTextColor(hdc, RGB(0, 0, 0));
   
        // 获取客户区矩形  
        RECT clientRect;
        GetClientRect(hwnd, &clientRect);
        // 计算文本的大小  
        SIZE textSize;
        GetTextExtentPoint32(hdc, text, length, &textSize);  
        //文本的位置是窗口客户区宽度和高度的一半
        int x = (clientRect.right - textSize.cx) / 2;
        int y = (clientRect.bottom - textSize.cy) / 2;
       // 绘制文本 
        TextOut(hdc,x ,y , text, length);
      
        //结束绘画操作,将绘画结果提交到屏幕上。
        EndPaint(hwnd, &ps);
        break;
    } 
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);//转给windows处理,默认的窗口过程
    }
    return 0;
}

运行结果

实验小结

本次实验重点为窗口的创建流程,将注册窗口类和创建显示窗口的代码封装在函数中,主函数中只要调用即可。
在创建完窗口后,使用

PlaySound(_T("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC| SND_LOOP);

同步循环播放音乐。
绘制文本的内容在
https://www.cnblogs.com/wa2211lq/p/18540637
有详细说明

posted @ 2024-11-11 21:52  刘倩_网安2211  阅读(22)  评论(0编辑  收藏  举报