2016-10-16 2 views
0

У меня возникли проблемы с отображением моего отображаемого изображения .bmp на другое, введенное пользователем. Изображение можно успешно распечатать в начале (title.bmp), но предполагается, что при нажатии 1 или 2 следует ввести (до introduction.bmp & start.bmp). Я должен что-то упустить!C++ изменение изображения при вводе пользователя в WinAPI

Где это происходит, находится в нижней части кода от 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; 
     } 
    } 
+0

Пожалуйста, прочитайте хорошую книгу по программированию Windows (например, [Программирование Windows®, пятое издание] (https://www.amazon.com/dp/157231995X)). Если вы нетерпеливы, просмотрите этот учебник: [Learn to Program for Windows in C++] (https://msdn.microsoft.com/en-us/library/windows/desktop/ff381399.aspx). Не ожидайте знания из учебника. – IInspectable

+0

Возможно, вы используете MinGW в режиме отладки, он показывает окно консоли для отчета об отладке. Окончательная версия вашего приложения должна быть в режиме «release», в этой версии не будет сопутствующего консольного окна. –

ответ

0

вы не можете использовать CIN в win32 использовать EditBox затем получить ввод пользователя от него, как строка символов, а затем, если вы хотите преобразовать его в целое значение в противном случае использовать API:

GetDlgItemInt(...); 

вы также обрабатывает только GetMessage во время цикла, в то время как вы обрабатываете только диспетчерское сообщение за пределами цикла, что означает, что вы обрабатываете его только один раз, когда getmessage терпит неудачу (конец программы), поэтому результатом является замораживание окон, пока никто не принимает сообщения от getmessage к целевому ветру.

решение: сделать DispatchMessage внутри цикла While:

  • другое: вы передаете HWND, чтобы GetMessage результат разрушающего окно не будет делать выход приложения.

взглянуть на GetMessage() при прохождении ненулевое значение: link text

правильная вещь в вашем случае:

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

* не загружать изображения внутри цикла просто нагрузка в нужное время:

сделайте поле редактирования со стилем ES_NUMBER и другими именами кнопок, например, измените изображение, чтобы при щелчке взять содержимое поля редактирования, преобразовать его в целое число, проверьте, будет ли это 1 или 2, затем загрузите изображение в зависимости от значения.

  • вы можете спросить «почему я не могу использовать входные и выходные потоки iostream в win32», потому что я спрашиваю вас «где консольные окна?» и если он здесь, то какова роль while-loop (блокировка ожидания сообщений)?