c++在WinAPI中根据用户输入改变图像

C++ changing image on user input in WinAPI

本文关键字:用户 输入 改变 图像 WinAPI c++      更新时间:2023-10-16

我在获得我的。bmp图像显示更改为另一个用户输入的问题。图像可以在开始时(title.bmp)成功打印,但应该在按1或2后按enter(到introduction.bmp &start.bmp)。我一定是错过了什么!

发生这种情况的地方是在while (running == 1) {代码的底部,所以跳到那里。我使用loadImage("title.bmp");来打印我的图像(当然我适当地更改了文件名),cin >> menuSelection;暂停程序并等待,直到用户按下一或两个然后输入。

我已经搜索了很多,很多关于如何在WinAPI中打印和更改图像的页面,这是我能得到的最接近的。如果我还遗漏了什么信息,请告诉我,我将予以评论。提前感谢你的帮助!

//These are the libraries (external files) to include at the start.
#include <cstdio>
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string>
using namespace std;
//Defining the [global] variables that will be used throughout the program
int running = 1;
int menuSelection = 0;
int userInput;
int userInputDummy;
int intPointer;
//Starter variables used in creating a window and printing images. These are global.
HDC         imageDC;        // the DC to hold our image
HBITMAP     imageBmp;       // the actual bitmap which contains the image (will be put in the DC)
HBITMAP     imageBmpOld;    // the DC's old bitmap (for cleanup)
const int   screenSize_X = 640;
const int   screenSize_Y = 480;
//Functions! Sections of code to re-used in the program
// Function to load the image into our DC so we can draw it to the screen
void loadImage(const char* pathname)
{
    imageDC = CreateCompatibleDC(NULL);     // create an offscreen DC
    imageBmp = (HBITMAP)LoadImageA(         // load the bitmap from a file
        NULL,                           // not loading from a module, so this is NULL
        pathname,                       // the path we're loading from
        IMAGE_BITMAP,                   // we are loading a bitmap
        0, 0,                            // don't need to specify width/height
        LR_DEFAULTSIZE | LR_LOADFROMFILE// use the default bitmap size (whatever the file is), and load it from a file
        );
    imageBmpOld = (HBITMAP)SelectObject(imageDC, imageBmp);  // put the loaded image into our DC
}
// Function to clean up
void cleanUpImage()
{
    SelectObject(imageDC, imageBmpOld);      // put the old bmp back in our DC
    DeleteObject(imageBmp);                 // delete the bmp we loaded
    DeleteDC(imageDC);                      // delete the DC we created
}
// The function to draw our image to the display (the given DC is the screen DC)
void drawImage(HDC screen)
{
    BitBlt(
        screen,         // tell it we want to draw to the screen
        0, 0,            // as position 0,0 (upper-left corner)
        screenSize_X,   // width of the rect to draw
        screenSize_Y,   // height of the rect
        imageDC,        // the DC to get the rect from (our image DC)
        0, 0,            // take it from position 0,0 in the image DC
        SRCCOPY         // tell it to do a pixel-by-pixel copy
        );
}
// A callback to handle Windows messages as they happen
LRESULT CALLBACK wndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l)
{
    // what kind of message is this?
    switch (msg)
    {
        // we are interested in WM_PAINT, as that is how we draw
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC screen = BeginPaint(wnd, &ps);   // Get the screen DC
        drawImage(screen);                  // draw our image to our screen DC
        EndPaint(wnd, &ps);                  // clean up
    }break;
    // we are also interested in the WM_DESTROY message, as that lets us know when to close the window
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    // for everything else, let the default window message handler do its thing
    return DefWindowProc(wnd, msg, w, l);
}
// A function to create the window and get it set up
HWND createWindow(HINSTANCE inst)
{
    WNDCLASSEX wc = { 0 };        // create a WNDCLASSEX struct and zero it
    wc.cbSize = sizeof(WNDCLASSEX);     // tell windows the size of this struct
    wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));        // tell it to use the normal arrow cursor for this window
    wc.hInstance = inst;                   // give it our program instance
    wc.lpfnWndProc = wndProc;                // tell it to use our wndProc function to handle messages
    wc.lpszClassName = TEXT("DisplayImage");   // give this window class a name.
    RegisterClassEx(&wc);           // register our window class with Windows
                                    // the style of the window we want... we want a normal window but do not want it resizable.
    int style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;    // normal overlapped window with a caption and a system menu (the X to close)
                                                            // Figure out how big we need to make the window so that the CLIENT area (the part we will be drawing to) is
                                                            //  the desired size
    RECT rc = { 0,0,screenSize_X,screenSize_Y };      // desired rect
    AdjustWindowRect(&rc, style, FALSE);              // adjust the rect with the given style, FALSE because there is no menu
    return CreateWindow(            // create the window
        TEXT("DisplayImage"),       // the name of the window class to use for this window (the one we just registered)
        TEXT("Display an Image"),   // the text to appear on the title of the window
        style | WS_VISIBLE,         // the style of this window (OR it with WS_VISIBLE so it actually becomes visible immediately)
        100, 100,                    // create it at position 100,100
        rc.right - rc.left,         // width of the window we want
        rc.bottom - rc.top,         // height of the window
        NULL, NULL,                  // no parent window, no menu
        inst,                       // our program instance
        NULL);                      // no extra parameter
}
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//  _________________________________________________________________________________________
    // The actual entry point for the program!
    //  This is Windows' version of the 'main' function:
    int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd, int show)
    {
        // load our image
        loadImage("title.bmp");
        // create our window
        HWND wnd = createWindow(inst);
        // Do the message pump!  keep polling for messages (and respond to them)
        //  until the user closes the window.
        MSG msg;
        while (GetMessage(&msg, wnd, 0, 0)) // while we are getting non-WM_QUIT messages...
        TranslateMessage(&msg);     // translate them
            DispatchMessage(&msg);      // and dispatch them (our wndProc will process them)
            {
            while (running == 1) {
                //Welcoming the user to the program, and asking them what they want to do (starts functions)
                cin >> menuSelection;
                //Selecting the introduction option
                if (menuSelection == 1) {
                    loadImage("introduction.bmp");
                    cin >> userInputDummy;
                    menuSelection = 0;
                }
                //Selecting the start option
                else if (menuSelection == 2) {
                    loadImage("start");
                    cin >> userInputDummy;
                    menuSelection = 0;
                }
                //Selecting the exit option
                else if (menuSelection == 3) {
                    menuSelection = 0;
                    running = 0;
                }
            }
            // once the user quits....
            cleanUpImage();
            return 0;
            return EXIT_SUCCESS;
        }
    }

你不能在win32中使用cin,使用编辑框然后从它作为字符串获取用户的输入,然后如果你想将其转换为整数值,否则使用API:

GetDlgItemInt(...);

你也只在while-loop中处理GetMessage,而你只在循环外处理dispatchmessage,这意味着你只处理一次,当GetMessage失败时(程序结束),所以结果是一个冻结窗口,只要没有人从GetMessage获取消息到目标窗口。

解决方案:在while循环中使用DispatchMessage:

  • 另一件事:你传递hwnd给getmessage,结果销毁窗口不会使应用程序退出。

看一下GetMessage()传递非空值时的情况:链接文本

正确的事情在你的情况:

while (GetMessage(&msg, 0, 0, 0) > 0)
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

*不要在循环内加载图像,只在需要的时间加载:

创建一个样式为ES_NUMBER的编辑框和另一个按钮名称,例如,更改图像,当单击时,将编辑框的内容转换为整数,检查它是1还是2,然后根据值加载图像。

  • 你可能会问"为什么我不能在win32中使用iostream输入和输出流",因为我问你"控制台窗口在哪里?"如果它在这里,while-loop(阻塞等待消息)的作用是什么?