【问题标题】:Print text and images in C++ (WinAPI or QT)在 C++(WinAPI 或 QT)中打印文本和图像
【发布时间】:2016-08-18 12:26:40
【问题描述】:

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

非常感谢任何具体的帮助,因为我已经坚持了 10 多周!在这里在线询问是我最后的选择。

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

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

我首先在microsoft visual studio中使用我的计算机附带的WinAPI,并尝试了其他已经回答的类似问题的许多不同建议,但总是遇到两个问题之一; 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

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

【问题讨论】:

  • 那么,您是在问如何在 Win32 中更改文本内容,还是在问其他问题?我真的不明白你在寻求什么帮助。
  • 如果可能的话,我想知道如何在 WinAPI 中更改文本内容,一旦已经打印了其他内容,并且一旦不碍事,我需要帮助才能显示图像(在文本,而不是替换它),也可以被替换。

标签: c++ image qt text


【解决方案1】:
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。你的代码到处都是。你有像std::string这样的C++14类,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;
}

【讨论】:

  • 顺便说一下,为了让事情更清楚,我应该把std::string text = vec[sel]放在std::string text = vec[sel]然后你用TextOut(hdc, 0, 0, text.c_str(), text.size())打印文本。请参阅此example 以获取解释std::vectorstd::string
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-10
  • 1970-01-01
  • 1970-01-01
  • 2015-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多