Hileb 发表于 2022/8/27 15:27

c艹,在Dev-c++中制造窗口!(更新中)

本帖最后由 Hileb 于 2022/10/3 17:45 编辑

制造窗口于信息!
首先,需要有一个窗口:下面是Dev-C++提供的一个示例:
#include <windows.h>

/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
        switch(Message) {
               
                /* Upon destruction, tell the main thread to stop */
                case WM_DESTROY: {
                        PostQuitMessage(0);
                        break;
                }
               
                /* All other messages (a lot of them) are processed using default procedures */
                default:
                        return DefWindowProc(hwnd, Message, wParam, lParam);
        }
        return 0;
}

/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
        WNDCLASSEX wc; /* A properties struct of our window */
        HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
        MSG msg; /* A temporary location for all messages */

        /* zero out the struct and set the stuff we want to modify */
        memset(&wc,0,sizeof(wc));
        wc.cbSize               = sizeof(WNDCLASSEX);
        wc.lpfnWndProc       = WndProc; /* This is where we will send messages to */
        wc.hInstance       = hInstance;
        wc.hCursor               = LoadCursor(NULL, IDC_ARROW);
       
        /* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wc.lpszClassName = "WindowClass";
        wc.hIcon               = LoadIcon(NULL, IDI_APPLICATION); /* Load a standard icon */
        wc.hIconSm               = LoadIcon(NULL, IDI_APPLICATION); /* use the name "A" to use the project icon */

        if(!RegisterClassEx(&wc)) {
                MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
                return 0;
        }

        hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, /* x */
                CW_USEDEFAULT, /* y */
                640, /* width */
                480, /* height */
                NULL,NULL,hInstance,NULL);

        if(hwnd == NULL) {
                MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
                return 0;
        }

        /*
                This is the heart of our program where all input is processed and
                sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
                this loop will not produce unreasonably high CPU usage
        */
        while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
                TranslateMessage(&msg); /* Translate key codes to chars if present */
                DispatchMessage(&msg); /* Send it to WndProc */
        }
        return msg.wParam;
}
这段代码的意思非常容易看懂,int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)相当于main,但是如果有main,那么会发生什么呢?你可以自己试试。
它创建看一个窗口,设置它,显示它,然后进入了一个循环:
/*
                This is the heart of our program where all input is processed and
                sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
                this loop will not produce unreasonably high CPU usage
        */
        while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
                TranslateMessage(&msg); /* Translate key codes to chars if present */
                DispatchMessage(&msg); /* Send it to WndProc */
        }
显然,这个循环是程序的核心,如果把它删除,那么窗口在显示出来后程序便结束了。
在这个循环中,接受消息,翻译消息,发送消息。

在LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)中,我们可以进行一些事情,从Dev-C++所给出的示例可以看出,当WM_DESTROY时,会PostQuitMessage(0);。其他按默认方式处理。
我们可以加上一些东西:
case WM_CLOSE:{
                       
                        break;
                }
这时,你会发现点击小叉叉没办法关闭窗口了,因为点击小叉叉时WM_CLOSE,因为WM_CLOSE时什么也不干,所以按小叉叉也不会有什么功能。
现在,加上一句:
MessageBox(hwnd,"helloworld","helloworld",NULL);
这时,按下叉叉会显示helloworld。
菜单与信息
你可以在WinMain中加上:
wc.lpszMenuName= "MAINMENU";
它可以使得你的窗口有一个菜单
你可以新建一个叫resource.rc的文件在你的工程里:
可以这么写:

MAINMENU MENU
{
POPUP "&母"
{
MENUITEM "&子1", 1000
MENUITEM "&子2", 1001
MENUITEM SEPARATOR//横线
MENUITEM "子3", 1002
POPUP "&再嵌套"
{
MENUITEM "&子子", 1003
}
}
MENUITEM "1004", 1004
}
然后再他们被按下时:会有WM_COMMAND,你可以这样处理:
case WM_COMMAND:{
                        switch(LOWORD(wParam)) {
                                case 1002:{
                                        MessageBox(hwnd,"helloworld","1002",NULL);
                                        break;
                                }
                                case 1004:
                                        MessageBox(hwnd,"helloworld","1004",NULL);
                                        break;
                        }
                        break;
                }
显然,在按下“子3”时,会显示1002,按下“1004”时,会显示1004.
然后,你就可以自由地发挥去做你的菜单了!
绘图与信息
你可以在LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)中,加入:
PAINTSTRUCT ps;//画笔
        HDC hdc;//绘图句柄

case WM_PAINT:{
                        //开始绘图
                        hdc=BeginPaint(hwnd,&ps);
                        //绘图
                        //Windows_paint(hdc,hwnd);
                        //结束绘图
                        EndPaint(hwnd,&ps);
                        break;
                }
然后你就可以绘图了!
先绘制一行文字,有一个简单的方法:
TextOut(hdc,0,0,"绘制一行文字!",12);
当然,放在这里会显得特别地,不好看,所以,加一个:
void Windows_paint(HDC hdc,HWND hwnd){
        //两次加载
        //获取客户端大小
        RECT rt;
        GetClientRect(hwnd,&rt);
        int WC_width=rt.right-rt.left;
        int WC_higth=rt.bottom-rt.top;
        //创建位图
        HBITMAP background=CreateCompatibleBitmap(hdc,WC_width,WC_higth);
        //创建兼容DC
        HDC ohdc=CreateCompatibleDC(hdc);
        SelectObject(ohdc,background);
        //绘制物品
        TextOut(hdc,0,0,"绘制一行文字!",12);
        //合并
        BitBlt(hdc,0,0,WC_width,WC_higth,ohdc,0,0,SRCCOPY);
}
你可以用InvalidateRect(hwnd,NULL,TRUE);去更新;
-----显示图片!-----
一个全局变量:
HINSTANCE this_windows;
在WinMain中将它初始化:
this_windows= hInstance;
加上:
voidPaint_background(HWND hwnd,HDC hdc,LPCSTR str){//绘制一张图片的实验
        //加载图片
        HBITMAP bitmap=(HBITMAP)(LoadImageA(this_windows,str,IMAGE_BITMAP,0,0,0x0010));
        HDC ohdc=CreateCompatibleDC(hdc);
        SelectObject(ohdc,bitmap);
        //贴图
        BitBlt(hdc,0,0,
        640,//图片宽度
        480,//图片高度
        ohdc,0,0,SRCCOPY);
}
然后在Windows_paint中加上:
Paint_background(hwnd,ohdc,"1.bmp");
//(一般都是后面挡住前面,例如Paint_background在TextOut后,则会将其挡住。)
然后就可以显示准备好的640x480的1.bmp(也可以把大小作为参数)
------绘制假按钮!--------
class Button{
        public:
                bool isEmpty=true;
                int stx;//Æeê¼x
                int sty;//Æeê¼y
                int _x;//x
                int _y;//y
                LPCSTR path;//bmp·¾¶ Î′Ñ¡Ôñ
//                LPCWSTR road2;//òÑÑ¡Ôñ
//                LPCWSTR road3;//òÑ°′ÏÂ
                bool isDown=0;
                bool *show;
                //éèÖÃ
                set(int x,int y,int x_,int y_,LPCSTR str,bool *show_){
                        stx=x;
                        sty=y;
                        _x=x_;
                        _y=y_;
                        path=str;
                        isEmpty=false;
                        show=show_;
                }
       
};
Button newButton(int x,int y,int x_,int y_,LPCSTR str,bool *show_){
        Button button;
        button.set(x, y, x_,y_,str,show_);
        return button;
}
voidpaint_button(HWND hwnd,HDC hdc,Button button){//»æÖÆò»ÕÅí¼Æ¬μÄêμÑé
        //¼óÔØí¼Æ¬
        if(*(button.show)==true){
                HBITMAP bitmap=(HBITMAP)(LoadImageA(this_windows,button.path,IMAGE_BITMAP,0,0,0x0010));
        //»æÖÆí¼Æ¬
        //′′½¨DC
        HDC ohdc=CreateCompatibleDC(hdc);
        SelectObject(ohdc,bitmap);
        //ìùí¼
        BitBlt(hdc,button.stx,button.sty,
        (button._x),//í¼Æ¬¿í′ø
        (button._y),//í¼Æ¬¸ß¶è
        ohdc,0,0,SRCCOPY);
        }
}
bool canshow=true;
Button button1=newButton(10,10,10,10,"button.bmp",&canshow);
在Windows_paint中加入:
paint_button(hwnd,ohdc,button1);
在case 1004:中加入:
canshow=!canshow;
InvalidateRect(hwnd,NULL,TRUE);
当canshow为true时,按键会显示,而按1004会改变canshow且刷新!
------使按钮会被按到!--------
在classButton中加入:
in(int x,int y){
                        if(x>=stx && x<=(stx+_x) && y>=sty && y<=(sty+_y))return true;
                        else false;
                }
在WndProc加入:
case WM_LBUTTONDOWN:{//点击鼠标左键时
                        //获取点击坐标
                        int cx=LOWORD(lParam);
                        int cy=HIWORD(lParam);
                        //
                        if(*(button1.show)==true){
                                if(button1.in(cx,cy)){
                                        canshow=!canshow;
                                }
                        }
                       
                        InvalidateRect(hwnd,NULL,TRUE);//更新
                        break;
                }
当鼠标点击,按钮显示,且按钮的区域被点击时,canshow发生改变,表现为按下按钮后按钮消失!

当然,你也可以修改class Button,让它有多个贴图和多个状态,例如:
WM_MOUSEMOVE//鼠标移动,鼠标指着按钮时按钮高亮。
按钮被点击颜色变深。。。以及一些别的。。。
也可以加一个class Buttons去批量管理Button,而不用手动去搞,
毕竟这样的东西是可以cv的{:3323:}


------------------------------------
正常人前端后端都要有的啦!
https://www.cnblogs.com/DOMLX/p/9601511.html
------------------------------------
你可以在winuser.h里找到WM_XXXXX,根据它的名字,你应该知道怎么用;
------------------------------------
一个小工程:github:solar stories v1.14.5.14

小樱 发表于 2022/8/27 18:48

这可能就是大佬吧。。写了这么多忙猜花了一小时!

Hileb 发表于 2022/8/27 19:03

本帖最后由 Hileb 于 2022/8/28 09:22 编辑

小樱 发表于 2022/8/27 18:48
这可能就是大佬吧。。写了这么多忙猜花了一小时!

不,这个是根本不看windows给了什么api就瞎做的小白

小樱 发表于 2022/8/28 00:34

https://developer.mozilla.org/zh-CN/docs/WebAssembly/Concepts
浏览器里好像可以运行rust/C/C艹

Hileb 发表于 2022/8/28 10:22

小樱 发表于 2022/8/28 00:34
https://developer.mozilla.org/zh-CN/docs/WebAssembly/Concepts
浏览器里好像可以运行rust/C/C艹

好高级!
页: [1]
查看完整版本: c艹,在Dev-c++中制造窗口!(更新中)