Изображение не будет отображаться на экране C ++ - PullRequest
0 голосов
/ 23 февраля 2010

Я следую учебному пособию. И я пытаюсь нарисовать файл .bmp на экране. Он строится без ошибок, но изображение не появляется. согласно книге, я должен увидеть всплывающее изображение в случайных местах. Ниже мой код. Автор не рекомендует эту технику для рисования объектов, он просто делает для демонстрации. На случай, если вам интересно.

Изображение представляет собой красный квадрат 25х25.

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

using namespace std;

const string APPTITLE = "Game Loop";
HWND window;
HDC device;
bool gameover = false;


void DrawBitmap(char *filename, int x, int y)
{
 //load the bitmap image
 HBITMAP image = (HBITMAP)LoadImage(0,"c.bmp", IMAGE_BITMAP,0,0, LR_LOADFROMFILE);

 BITMAP bm;
 GetObject(image, sizeof(BITMAP), &bm);

 HDC hdcImage = CreateCompatibleDC(device);
 SelectObject(hdcImage,image);

 BitBlt(
  device,
  x,y,
  bm.bmWidth, bm.bmHeight,
  hdcImage,
  0,0,
  SRCCOPY);

 //deletec the device context and bitmap
 DeleteDC(hdcImage);
 DeleteObject((HBITMAP)image);
}

bool Game_Init()
{
 srand(time(NULL));
 return 1;
}

void Game_Run()
{
 if(gameover == true) return;

 RECT rect;
 GetClientRect(window, &rect);

 //draw bitmap at random location
 int x = rand() % (rect.right - rect.left);
 int y = rand() % (rect.bottom - rect.top);

 DrawBitmap("c.bmp",x,y);
}

void Game_End()
{
 //free the device
 ReleaseDC(window,device);
}

LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM WParam, LPARAM lparam)
{
 switch(message)
 {
  case WM_DESTROY:
   gameover = true;
   PostQuitMessage(0);
  break;
 }

 return DefWindowProc(hWnd, message, WParam, lparam);
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
 //set the new windows properties

 WNDCLASSEX wc;

 wc.cbSize  = sizeof(WNDCLASSEX);
 wc.style  = CS_HREDRAW | CS_VREDRAW;
 wc.lpfnWndProc = (WNDPROC) WinProc;
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hInstance = hInstance;
 wc.hIcon  = NULL;
 wc.hCursor  = LoadCursor(NULL, IDC_ARROW);
 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
 wc.lpszMenuName = NULL;
 wc.lpszClassName= APPTITLE.c_str();
 wc.hIconSm  = NULL;

 return RegisterClassEx(&wc);
}

bool InitInstance(HINSTANCE hInstance, int nCmdShow)
{
 //create a  new window
 window = CreateWindow(
  APPTITLE.c_str(),
  APPTITLE.c_str(),
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, CW_USEDEFAULT,
  640,480,
  NULL,
  NULL,
  hInstance,
  NULL);

 //was there an error creating the window ?
 if(window == 0) return 0;

 //display the window 
 ShowWindow(window, nCmdShow);
 UpdateWindow(window);
 device = GetDC(window);

 return 1;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
      LPSTR lpCmdLine, int nCmdShow)
{
 //declare variables
 MSG msg;

 //register the class
 MyRegisterClass(hInstance);

 //initialize application
 if(!InitInstance(hInstance, nCmdShow)) return 0;

 //initilize the game
 if(!Game_Init()) return 0;

 //main message loop
 while(!gameover)
 {
  if(PeekMessage(&msg,NULL, 0, 0,PM_REMOVE))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
  Game_Run();
 }

 Game_End();

 return msg.wParam;
}

Я не уверен, что это потому, что у меня изображение не в том месте. но если бы это было так. Я полагаю, что это приведет к ошибке. Я разместил изображение в корне папки с исходным кодом.

[EDIT]

Также, когда я перестраиваюсь, я получаю предупреждение, которое может быть причиной, но вот предупреждение

1>------ Rebuild All started: Project: Begin, Configuration: Debug Win32 ------
1>Deleting intermediate and output files for project 'Begin', configuration 'Debug|Win32'
1>Compiling...
1>main.cpp
1>c:\users\numerical25\documents\visual studio 2008\projects\begin\begin\main.cpp(39) : warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data
1>Compiling manifest to resources...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>Linking...
1>LINK : C:\Users\numerical25\Documents\Visual Studio 2008\Projects\Begin\Debug\Begin.exe not found or not built by the last incremental link; performing full link
1>Embedding manifest...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>Build log was saved at "file://c:\Users\numerical25\Documents\Visual Studio 2008\Projects\Begin\Begin\Debug\BuildLog.htm"
1>Begin - 0 error(s), 1 warning(s)
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

alt text

Ответы [ 2 ]

5 голосов
/ 23 февраля 2010

Код работает, вы просто забыли поставить c.bmp в нужном месте. Поместите его в выходную папку проекта (например, bin / Debug), если вы запускаете программу из Проводника, или в папку проекта, если вы запускаете программу из Visual Studio.

0 голосов
/ 23 февраля 2010

Ваш код, кажется, работает, для достаточно свободного определения «работы». Если вы не изменили код (совсем немного), пытаясь заставить его работать, я бы посоветовал найти другой учебник для подражания - по крайней мере для меня, большая часть того, что есть сейчас, совершенно не впечатляет.

Например, Game_Run() передает имя файла растрового изображения в качестве параметра в Draw_Bitmap(), но параметр игнорируется, а Draw_Bitmap() использует вместо него жестко закодированное имя файла.

Цикл PeekMessage() делает программу похожей на ту, что была написана около 25 лет назад, во времена 16-битной Windows (и, возможно, не так уж и хороша даже тогда). Редко (если вообще) есть веская причина для использования PeekMessage() в новом коде, и код, который его использовал, вероятно, просрочен для капитального ремонта. Основной цикл обычно использует GetMessage(), и вы можете (например) использовать SetTimer (с длительностью 0), чтобы вычислить новые координаты для рисования растрового изображения, а затем вызвать InvalidateRect(), чтобы нарисовать его. Когда-то был справедливый аргумент, что дополнительные сообщения, связанные с этим, вызывали чрезмерные издержки, но на современной машине он будет поддерживать частоту обновления монитора при использовании порядка 10% ЦП или меньше.

Однако, чтобы снизить нагрузку на процессор, вам нужно немного реструктурировать код - прямо сейчас, каждый раз, когда вы рисуете, вы получаете прямоугольник окна, перезагружаете BMP с диска, выбираете BMP в совместимый DC и, наконец, BitBlt, чтобы вывести изображение на экран. Это та часть кода, где оптимизация будет иметь значение - в силу сильных предпочтений вы хотите, чтобы просто позвонил BitBlt и все было сделано. Остальная часть кода должна быть перемещена в другое место, так что это происходит только при необходимости. Например, вы можете получить прямоугольник окна в ответ на WM_SIZE и просто сохранить его между ними. Поскольку вы используете одно и то же растровое изображение на время, загрузите его один раз, и из них просто отобразите его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...