c++ - 在 C++(WinAPI 或 QT)中打印文本和图像

标签 c++ image qt text

在一个基本程序中,我需要知道如何制作一个文本显示小部件和图像显示,它们都可以根据命令更改为不同的字符串和图像。这些将显示在基本 GUI 上。

任何具体的帮助将不胜感激,因为我已经坚持了 10 多个星期!在这里在线询问是我最后的选择。

我正在制作一个提出问题的基本程序(这是我要打印的文本),问题的图像出现在它下面。我已经在控制台命令窗口中成功制作了这个程序(我将在下面分享代码)但这当然意味着无法显示图像,所以我不得不在支持图像的 GUI 中重新制作它。

这是我用 C++ 完成的第一个项目,并且只了解基础知识(我有限的知识让我在没有帮助的情况下制作了控制台命令窗口程序)。

我第一次使用 WinAPI 是因为它在我的计算机中是在 Microsoft Visual Studio 中,并尝试了其他人已经回答过的类似问题的许多不同建议,但总是有两个问题之一; 1. 他们提供的代码有很多错误,其中大多数是“_ 未定义”或未正确导入,或者 2. 成功创建了基本文本,但没有指定创建后如何更改它(我有过到目前为止还没有成功的图像打印)。我已经尝试了来自 cplusplus.com 的 3 个问题/答案和来自堆栈溢出的 3 个问题/答案(链接将在下面),所有这些问题/答案都是由于我缺乏 C++ 错误修复技能而造成的。

使用 WinAPI 的建议优先于 QT,因为我不知道我在 Qt 中做什么,并且在我导入代码时得到两位数的错误(即使我导入了正确的目录),而 WinAPI 没有得到导入错误。

命令控制台程序代码:

//G-Learning
//@author: James Monk
//@completed: 7/6/16
//@version 1.0

//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;
int questionsLeft = 5;
int questionTextPicked;
int questionImagePicked;
int questionRandomised;
int score = 0;
int userInput;
int userInputDummy;

string stringPointer;
int intPointer;

string questionText[10] = {
    "Would this most likely be, (1) an enemy (2) a player?\n",
    "Is this (1) how many hearts the player has inside their body, or (2) a number of lives the player has?\n", 
    "Is this (1) a health bar, or (2) a set of red lights?\n",
    "Is this (1) a money counter, or (2) a yellow ball counter?\n",
    "Would this be a good object to touch with your character? (1) no or (2) yes?\n",
    "What would this object likely have in it? (1) rewards, or (2) punishments\n", 
    "What does 'Game Over' mean? (1) your session has ended, or (2) the game is no longer playable\n", 
    "What would an icon like this likely be for? (1) show wheels, or (2) options\n", 
    "In a racing game, what would this be for? (1) health bar, or (2) fuel tank meter\n", 
    "What would this button likely do? (1) exit or cancel, or (2) mark a spot with an x\n" };

//Defining what happens with the different functions
void introduction() {
    printf("\nG-Learning is a program built to teach people who know little about games the basic features of them. \n\n\
Questions will be asked, and you will need to answer them by choosing the correct answer.\n\
You will need to press 1, 2, or 3 followed by enter to choose.\n\n\
Press any number key followed by enter to return to the main menu.\n\n");
    cin >> userInputDummy;
    menuSelection = 0;
}

void start() {
    printf("\nThe questions will now start, good luck!\n\n");
    while (questionsLeft > 0) {
        questionTextPicked = (rand() % 10);
        if (questionTextPicked == 0) {
            questionRandomised = (rand() % 4);
            questionImagePicked = (7 + questionRandomised);
        } 
        else if (questionTextPicked == 4) {
            questionRandomised = (rand() % 3);
            questionImagePicked = (11 + questionRandomised);
        }
        else {
            questionImagePicked = questionTextPicked;
        }
        printf("after calculations, questionTextPicked is %d, questionRandomised is %d, and questionImagePicked is %d\n\n", questionTextPicked, questionRandomised, questionImagePicked);

        //answering questions should be here
        stringPointer = questionText[questionTextPicked];
        intPointer = questionAnswer[questionImagePicked];

        printf("answer is %d\n\n", intPointer);
        printf("%s\n", stringPointer, intPointer);
        printf("answer is %d\n\n", intPointer);
        cin >> userInput;

        if (userInput == questionAnswer[questionImagePicked]) {
            printf("\nCorrect!\n\n");
            score++;
        }
        else {
            printf("\nIncorrect answer.\n\n");
        }
        questionsLeft--;

        if (questionsLeft > 0) {
            printf("%d questions to go!\n\n", questionsLeft);
        }

        if (questionsLeft == 0) {
            printf("All questions have been answered, you scored %d/5.\n\nReturning you to the main menu\n\n", score);
            score = 0;
        }
    } //end of start's while loop
    menuSelection = 0;
} //end of start's function

void exit() {
    menuSelection = 0;
    running = 0;
}

//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

    //Main function, where everything starts
    int main(int argc, char ** argv) {
        while (running == 1) {
            //Welcoming the user to the program, and asking them what they want to do (starts functions)
            printf("welcome to G-Learning! Press a key to get started.\n1: Instructions\n2: Start\n3: Exit\n\n");
            questionsLeft = 5; //Resetting this so that the start function can begin again
            cin >> menuSelection;

            if (menuSelection == 1) {
                introduction();
            }
            else if (menuSelection == 2) {
                start();
            }
            else if (menuSelection == 3) {
                exit();
            }
            else {
                printf("Invalid input, please use the 1, 2, or 3 key.");
            }
        }
        return 0;
        return EXIT_SUCCESS;
    } //end of main function

我最好的 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;

int textHorizontal = 10;
int textVertical = 10;

//Variables used in making the program window
int numberInput;
char charictorInput;
string stringInput;
const char g_szClassName[] = "myWindowClass";

HINSTANCE hInstance;

// Function to get the size of the text
int GetTextSize(LPSTR a0)
{
    for (int iLoopCounter = 0; ; iLoopCounter++)
    {
        if (a0[iLoopCounter] == '\0')
            return iLoopCounter;
    }
}

LPSTR TextArray[] = {
    "Hello World"
};

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        TextOut(hdc,
            // Location of the text
            textHorizontal,
            textVertical,
            // Text to print
            TextArray[0],
            // Size of the text, my function gets this for us
            GetTextSize(TextArray[0]));
        EndPaint(hwnd, &ps);
    }
    break;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int WINAPI WinMain(HINSTANCE hInstanace, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX WindowClass;
    WindowClass.cbClsExtra = 0;
    WindowClass.cbWndExtra = 0;
    WindowClass.cbSize = sizeof(WNDCLASSEX);
    WindowClass.lpszClassName = "1";
    WindowClass.lpszMenuName = NULL;
    WindowClass.lpfnWndProc = WndProc;
    WindowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WindowClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WindowClass.style = 0;
    WindowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    RegisterClassEx(&WindowClass);

    HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
        "1",
        "G-Learning by James Monk",
        WS_OVERLAPPEDWINDOW,
        315, 115,
        1080, 720,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hwnd, SW_SHOWNORMAL);

    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        if (VK_ESCAPE == msg.wParam)
            break;
    }
    return 0;
}

我仅限于 2 个链接,因此要查看我尝试过的 3 个 cplusplus.com 页面和我尝试过的 3 个堆栈溢出页面,它们的链接位于此处的 google 文档中: https://docs.google.com/document/d/1IX2hxzAVka3UmVkaAgv-gXv_cwwmP3FkTYQuFWrrqyE/edit?usp=sharing

我如何将 QT 安装到 Microsoft Visual Studio 中: https://www.youtube.com/watch?v=P6Mg8FpFPS8

感谢您阅读我的问题,更感谢您提前提供帮助!

最佳答案

HINSTANCE hInstance;
int WINAPI WinMain(HINSTANCE hInstanace...
CreateWindowEx(... hInstance ...)

你这里有拼写错误。 hInstanacehInstance 是不一样的。 Visual Studio 应该给你警告。将警告级别设置为 4。解决所有警告并修复它们。只有在极少数情况下才可以忽略警告。

此外,在 WNDCLASSEX WindowClass; 的声明中,您错过了初始化 hInstance,因此代码将无处可去。在 C++ 14 中你可以这样做

WNDCLASSEX WindowClass = {0}

这会将所有成员初始化为零。在堆栈上声明数据时,请尝试始终这样做。还要避免将随机代码放入消息循环中。

#include <cstdio>
#include <iostream>
#include <windows.h>

以上头文件用于 C 输入/输出、C++ 输入/输出和 WinAPI。通常你不需要全部。选择一个。

LPSTR TextArray[] = {
    "Hello World"
};

上面是一个字符数组,或者只是“文本”。如果您访问 TextArray[0],它会为您提供字符 'H'

int GetTextSize(LPSTR a0)
{
    for (int iLoopCounter = 0; ; iLoopCounter++)
    {
        if (a0[iLoopCounter] == '\0')
            return iLoopCounter;
    }
}

以上代码等同于strlen。你的代码到处都是。您有 C++14 类,如 std::string、C 头文件、无用函数(如 GetTextSize,主要用于学习 C/C++)、更高级的 WinAPI,以及一些提到Qt交叉开发。我建议您花更多时间阅读 C++ 书籍。以下是您正在尝试执行的操作的示例:

#include <windows.h>
#include <string>
#include <vector>

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HWND combobox;
    static std::vector<std::string> vec = {
        "Would this most likely be, (1) an enemy (2) a player?\n",
        "Is this (1) how many hearts the player has inside their body, or (2) a number of lives the player has?\n",
        "Is this (1) a health bar, or (2) a set of red lights?\n",
        "Is this (1) a money counter, or (2) a yellow ball counter?\n",
        "Would this be a good object to touch with your character? (1) no or (2) yes?\n",
        "What would this object likely have in it? (1) rewards, or (2) punishments\n",
        "What does 'Game Over' mean? (1) your session has ended, or (2) the game is no longer playable\n",
        "What would an icon like this likely be for? (1) show wheels, or (2) options\n",
        "In a racing game, what would this be for? (1) health bar, or (2) fuel tank meter\n",
        "What would this button likely do? (1) exit or cancel, or (2) mark a spot with an x\n"
    };

    switch (msg)
    {
    case WM_CREATE:
        combobox = CreateWindow("ComboBox", 0, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 0, 100, 700, 30, hwnd, HMENU(100), 0, 0);
        for (auto line : vec) SendMessage(combobox, CB_ADDSTRING, 0, LPARAM(line.c_str()));
        break;

    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
            DestroyWindow(hwnd);
        break;

    case WM_COMMAND:
        if (HIWORD(wParam) == CBN_SELCHANGE)
            InvalidateRect(hwnd, NULL, TRUE);
        break;

    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        int sel = SendMessage(combobox, CB_GETCURSEL, 0, 0);
        if (sel < 0) sel = 0;
        TextOut(hdc, 0, 0, vec[sel].c_str(), vec[sel].size());
        EndPaint(hwnd, &ps);
        break;
    }

    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wcx = { 0 };
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.lpszClassName = "ClassName";
    wcx.lpfnWndProc = WndProc;
    wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    RegisterClassEx(&wcx);

    HWND hwnd = CreateWindowEx(0, wcx.lpszClassName, "G-Learning by James Monk", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0,0,800,600, NULL, NULL, hInstance, NULL);

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

    return 0;
}

关于c++ - 在 C++(WinAPI 或 QT)中打印文本和图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39008634/

相关文章:

c++ - 由于动态数组导致的 HashMap 内存泄漏

c# - 从 Byte[] Asp.Net MVC 3 加载图像 Src

javascript - 通过调整 dropzone.js 压缩图像

python - 将 C++ 类移植到 PyQt

Ruby:在 Qt 中创建一个简单的应用程序

c++ - C++中文件的Big Endian和Little Endian

c++ - 使用 enable_if 的多个重载问题

image - 在ExtJS 4中,为什么setSrc()不更新图像

c++ - Qt 模糊 QMovie(来自 gif)

c++ - 如何使用 QT 每 15 秒调用一次函数