Problem z wyświetleniem bitmapy 7971 15

O temacie

Autor Tomaj

Zaczęty 18.12.2011 roku

Wyświetleń 7971

Odpowiedzi 15

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy

Tomaj

Problem z wyświetleniem bitmapy
2011-12-18, 21:33(Ostatnia zmiana: 2011-12-18, 21:46)
Witam.
    Postanowiłem zmierzyć się z samym sobą i stworzyć własną wersję starej już gry "kulki". Wszystko idzie jak należy, ale napotkałem problem i nie mam pomysłu jak go rozwiązać.
Chcę wyświetlić bitmapę w postaci kulki. Dołączam bitmapę w pliku Kulki.rc, który znajduje się w folderze resources. Na razie chciałem sprawdzić, czy funkcja wyświetlania bitmapy zadziała i instrukcję jej wyświetlenia napisałem w procedurze okna "WindowProcedure", w komunikacie "WM_CREATE". Napisałem warunek, który sprawdza czy zmienna "kulka_czerw" zadeklarowana jako zmienna "HBITMAP". Program ma wyświetlić okno z napisem "błąd", w przypadku nie załadowania pliku i niestety tak się właśnie dzieję.
  Proszę o pomoc. Programuję w darmowym kompilatorze Dev-C++ v. 4.9.9.1.
Oto kod pliku main.cpp:

#include <windows.h>
#include <windows.h>
#include "Kulki.h"
#include <mmsystem.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>

 

BITMAP bm;
/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           MaxX,                 /* The programs width */
           MaxY,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);
   
    HMENU menu = LoadMenu(hThisInstance, MAKEINTRESOURCE(ID_MENU));
    SetMenu(hwnd, menu);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     PAINTSTRUCT ps;  
     static int x_kursora, y_kursora;
     x_kursora = LOWORD(lParam);
     y_kursora = HIWORD(lParam);
    int przycisniecie;
    switch (message)                  /* handle the messages */
    {
      case WM_LBUTTONDOWN:
           
       
             InvalidateRect(hwnd, NULL, FALSE);
             break;

     
        case WM_CREATE:
             static HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
             static HWND hWndButton6 = CreateWindowEx(
             0,
             "BUTTON",
             "Nowa Gra",
             WS_CHILD | WS_VISIBLE | WS_EX_DLGMODALFRAME,
             40,
             570,
             160,
             50,
             hwnd,
             (HMENU) 106,
             hInst,
             NULL);    
           
             kulka_czerw = LoadBitmap(hInst, "K_Czerw.bmp");
             if(!kulka_czerw)
             {
                             MessageBoxA(hwnd, "błąd", "", 0);
             }
             kulka_zielona = LoadBitmap(hInst, "K_Ziel.bmp");
             kulka_niebieska = LoadBitmap(hInst, "K_Nieb");
             kulka_zolta = LoadBitmap(hInst, "K_Zol.bmp");
             kulka_pomaranczowa = LoadBitmap(hInst, "K_Poma.bmp");
           
             rect.left                = 5;
             rect.top                 = 5;
             rect.right               = 1000;
             rect.bottom              = 1000;
                break;
        case WM_COMMAND:
             switch(LOWORD(wParam))
             {
              case IDB_BUTTON1:
                   flaga = 1;
                   InvalidateRect(hwnd, &rect, FALSE);
                   break;                      
              case 106:
                   NowaGra();
                   break;
             }
             break;

        case WM_PAINT:
             
             hdc = BeginPaint(hwnd, &ps);
             hdc_czerw = CreateCompatibleDC(hdc);
             hdc_ziel  = CreateCompatibleDC(hdc);
             hdc_nieb  = CreateCompatibleDC(hdc);
             hdc_zol   = CreateCompatibleDC(hdc);
             SelectObject(hdc_czerw, kulka_czerw);
             SelectObject(hdc_ziel, kulka_zielona);
             SelectObject(hdc_nieb, kulka_niebieska);
             SelectObject(hdc_zol, kulka_czerw);
             SelectObject(hdc_poma, kulka_pomaranczowa);
             BitBlt(hdc, 342, 102, 400, 160, hdc_czerw, 342, 102, SRCCOPY);
             Rysuj(hdc);
             EndPaint(hwnd, &ps);
             break;
         
       
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}


Kulki.h:

#define ID_MENU         501
#define IDB_BUTTON1     101
#define IDB_BUTTON2     102
#define IDB_BUTTON3     103
#define IDB_BUTTON4     104
#define IDB_BUTTON5     105
#define IDB_BUTTON6     106
#include <math.h>
HBITMAP kulka_czerw, kulka_zielona, kulka_niebieska, kulka_zolta, kulka_pomaranczowa;
HDC hdc, hdc_czerw, hdc_ziel, hdc_nieb, hdc_zol, hdc_poma;
HWND hwnd;
//zmienne
const int MaxX = 978;
const int MaxY = 752;
int flaga;
int powtorzenie;
int kursor;
bool kratka1, kratka2, kratka3;
int kulka1, kulka2, kulka3;
int color1, color2, color3;
HFONT hFont;
RECT rect;

//Tablice
int xtable[] = {340, 402, 464, 526, 588, 650, 712, 774, 836};
int ytable[] = {100, 162, 224, 286, 348, 410, 472, 534, 596};
char colorsTable[] = {};
//Funkcje


void UtworzPole(int x, int y) //Rysuj pole gry
{
      Rectangle(hdc, x, y, x+60, y+60);  
}
   
 //Funkcja pola gry
 void Rysuj(HDC hdc)
{
               
         Rectangle(hdc, 1, 5, MaxX/3-70, MaxY-52);
      //Tytuł
      SetBkMode(hdc, TRANSPARENT);
      static LOGFONT lf;
      lf.lfHeight = 100;
      lf.lfWidth = 0;
      lf.lfEscapement = 0;
      lf.lfOrientation = 0;
      lf.lfWeight = 0;
      lf.lfItalic = 1;
      lf.lfUnderline = 1;
      lf.lfStrikeOut = 0;
      lf.lfCharSet = 0;
      lf.lfOutPrecision = 0;
      lf.lfClipPrecision = 0;
      lf.lfQuality = 0;
      lf.lfPitchAndFamily = 0;
      lstrcpy (lf.lfFaceName, TEXT ("Gabriola"));
     
      hFont = CreateFontIndirect(&lf);
     
      SelectObject(hdc, hFont);
      //tytuł
      TextOut(hdc, MaxX/2-21, 1, "Kulki", 18);
      //Okno z wynikiem
      lf.lfHeight = 50;
      lf.lfWidth = 0;
      lf.lfEscapement = 0;
      lf.lfOrientation = 0;
      lf.lfWeight = 0;
      lf.lfItalic = 0;
      lf.lfUnderline = 1;
      lf.lfStrikeOut = 0;
      lf.lfCharSet = 0;
      lf.lfOutPrecision = 0;
      lf.lfClipPrecision = 0;
      lf.lfQuality = 0;
      lf.lfPitchAndFamily = 0;
      lstrcpy (lf.lfFaceName, TEXT ("Gabriola"));
     
      hFont = CreateFontIndirect(&lf);
     
      SelectObject(hdc, hFont);
      TextOut(hdc, 50, 80, "Wynik: ", 6);
      Rectangle(hdc, 40, 120, 200, 190);
     
      //Okno z rekordem
      TextOut(hdc, 40, 210, "Najlepszy wynik: ", 16);
      Rectangle(hdc, 40, 250, 200, 320);
     
      // Ilość kolorów w grze
      TextOut(hdc, 40, 360, "Ilosc kolorów w grze: ", 23);
     
      //Następne kolory
      TextOut(hdc, 40, 420, "Następne kolory:", 16);
      Rectangle(hdc, 40, 460, 200, 530);
      Ellipse(hdc, 45, 470, 92, 520);
      Ellipse(hdc, 97, 470, 145, 520);
      Ellipse(hdc, 148, 470, 195, 520);
     
      //Pole gry
      int indexX;
      int indexY;
      for(int i=0; i<81; i++)
      {
              indexX = i%9;
              indexY = int(floor(i/9));
              UtworzPole(xtable[indexX], ytable[indexY]);
      }
     
}

void NowaGra()
{
     int pole;
     int xpola;
     int ypola;
     int losColor;
     for(int i=0; i<3; i++)
     {
             //losowanie pola
             pole=rand()%80;
             xpola=pole%9;
             ypola= int(floor(pole/9));
             //losowanie kolorów
             losColor=rand()%4;
     }
}
               

oraz Kulki.rc:

#include "Kulki.h"

kulka_czerw BITMAP "K_Czerw.bmp"
kulka_nieb BITMAP "K_Nieb.bmp"
kulka_ziel BITMAP "K_Ziel.bmp"
kulka_zol BITMAP "K_Zol.bmp"
kulka_poma BITMAP "K_Poma.bmp"

501 MENU
{
 POPUP "&Gra"
 {
       MENUITEM "&Nowa gra" , IDB_BUTTON1
       MENUITEM "&Zapisz grę" , IDB_BUTTON2
        MENUITEM "&Wczytaj grę" , IDB_BUTTON3
 }
 POPUP "&Opcje"
 {
        MENUITEM "&Opcje",    IDB_BUTTON4
 }  
 POPUP "&Pomoc"
 {
       MENUITEM "&Pomoc" , IDB_BUTTON5
 }
}

Wklejam cały kod, żeby była całkowita jasność.

Z góry dziękuję.
 

Adanos

Adanos

Administrator
Szara eminencja
posty5204
Propsy3870
ProfesjaProgramista
  • Administrator
  • Szara eminencja
A w jakim katalogu trzymasz bitmapy? Tam gdzie plik main.cpp?

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy
Tak. Wszystkie pliki znajdują się w jednym folderze.
 

oreca

oreca

Użytkownicy
posty196
Propsy72
Nagrody
Profesjabrak
  • Użytkownicy

oreca

Problem z wyświetleniem bitmapy
#3 2011-12-19, 20:33(Ostatnia zmiana: 2011-12-19, 20:35)
Spróbuj podać pełną ścieżkę do pliku.
Jeszcze spróbuj pokombinować z funkcją GetLastError() nie wiem czy w tym przypadku zadziała ale warto spróbować.
 

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy
Okej. Dzięki. Sprawdzę i dam znać.
 

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy
Niestety podanie pełnej ścieżki do pliku nic nie dało a i z funkcją GetLastError() niewiele udało mi się zwojować. Czy jeszcze ktoś ma jakieś pomysły?
 

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
Cytuj
Programuję w darmowym kompilatorze Dev-C++ v. 4.9.9.1.
To nie kompilator, tylko IDE. Wróć! To nie IDE, tylko gówno, które wydano 5 lat temu i od tamtego czasu nie aktualizowano.

Przerzuć się na coś sensownego, polecam najnowszy CodeBlocks z najnowszym GCC i opcjonalnie podpiąć pod to kompilator Microsoftu z Windows SDK (za darmo).

Co do tematu: W pliku *.rc tworzysz sobie zasoby, które zostaną poskładane do wynikowego PE EXE, to jakiego grzyba odwoływać się do tego nazwą? To nie plik, tylko zasób. Zgodnie z MSDN faktycznie do wczytywania zabawek z zasobów służy LoadBitmap. Użyj tego, co rekomendowali przy drugim argumencie. O ile się nie mylę, wynikowa postać jest następująca:
LoadBitmap(hInst, MAKEINTRESOURCE(kulka_czerw));
 

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy

Tomaj

Problem z wyświetleniem bitmapy
#7 2011-12-21, 11:57(Ostatnia zmiana: 2011-12-21, 12:05)
Dwie sprawy.

Pierwsza:
Dzięki za dobrą radę w sprawie Kompilatora. CodeBlocks już na pierwszy rzut oka wygląda lepiej i robi wrażenie bardziej profesjonalnego.

Druga:
Zamieniłem
kulka_czerw=LoadBitmap(hInst, ("K_Czerw.bmp"));

na

LoadBitmap(hInst, MAKEINTERSOURCE(kulka_czerw));

Teraz podczas kompilowania wyskakuje błąd o treści:
"|error: cast from 'HBITMAP__*' to 'WORD' loses precision|"

Nie jestem pewny co wstawić w nawias za "MAKEINTERSOURCE". Zauważyłem(dopiero teraz), że mam zadeklarowaną zmienną typu "HBITMAP" o nazwie "kulka_czerw" w pliku *.h oraz w pliku *.rc mam plik zasobu o takiej samej nazwie. Zmieniłem nazwę zasobu na "kulka_czerwona" i wstawiłem tę nazwę w nawias po "MAKEINTERSOURCE", ale wyskoczył mi błąd:
"error: 'kulka_czerwona' was not declared in this scope".

Która wersja powinna być prawidłowa?

 

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
Do `MAKEINTRESOURCE` powinien iść identyfikator zasobu.
Stwórz sobie jakiś nagłówek (najlepiej "resources.h") i w nim trzymaj definicje:

#pragma once

#define KULKA_CZERWONA 3001
#define KULKA_ZIELONA 3002
#define KULKA_ZIELONA 3003

Potem załącz go w pliku *.rc poprzez:
#include "resources.h"I nazwij swoje zasoby tak, jak w nagłówku powyżej. Preprocesor podstawi numerki za symbole.

I później jak już chcesz swoją koffaną bitmapę załadować w programie robisz:
kulka_czerw = LoadBitmap(hInst, MAKEINTRESOURCE(KULKA_CZERWONA));
Zmienna typu HBITMAP, a identyfikator zasobu to dwie różne rzeczy. Uchwyt do bitmapy jest zwracany przez `LoadBitmap`, identyfikatora potrzebujemy do drugiego argumentu.
 

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy
Ooo! Działa. Wielkie dzięki.
Teraz pozostało mi dowiedzieć się dlaczego bitmapa się nie wyświetla. Podejrzewam, że podałem złe argumenty. Mógłbym prosić o pomoc jeszcze w tej sprawie?
 

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
Mógłbym prosić o pomoc jeszcze w tej sprawie?
Oczywiście, jeśli będziesz miał jakiś konkretny problem do rozwiązania.

Cytuj
Teraz pozostało mi dowiedzieć się dlaczego bitmapa się nie wyświetla. Podejrzewam, że podałem złe argumenty.
Tak jak pisałem wyżej, pomylił Ci się identyfikator zasobu z uchwytem bitmapy. Tam się podaje wręcz na chama inta, który jest numerkiem zasobu z pliku *.rc, tylko używamy wersji z #define, leciuteńko bardziej cywilizowanej.
 

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy
Mówię teraz o fukncji "BitBlt();", która powinna wyświetlić bitmapę w podanym miejscu a tego nie robi.
Chyba, że podałeś mi już rozwiązanie, a ja znowu nie zrozumiałem.
U mnie funkcja ta wygląda tak:
BitBlt(hdc, 342, 102, 400, 160, hdc_czerw, 342, 102, SRCCOPY);
 

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
Pokaż kontekst. Ciężko cokolwiek z tego wywnioskować.
 

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy
W kodzie obsługi komunikatu "WM_CREATE:" załadowałem bitmapę tak jak powiedziałeś. Napisałem warunek sprawdzający czy bitmapa została załadowana i tak też się stało.
następnie w obsłudze komunikatu
"WM_PAINT:" napisałem następujące instrukcje:
hdc_czerw = CreateCompatibleDC(hdc);
SelectObject(hdc_czerw, kulka_czerw);
BitBlt(hdc, 342, 102, 400, 160, hdc_czerw, 342, 102, SRCCOPY);

Szczerze mówiąc nie wiem czy tak to powinno być zrobione.
Tak wnioskuję po przeczytaniu rozdziału o wyświetlaniu bitmap, w książce z której się uczę. Niestety książka nie wyjaśnia wszystkich kwestii i programuję często na "czuja", co jak wiadomo nigdy nie prowadzi do niczego dobrego.
 

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
http://www.winprog.org/tutorial/bitmaps.html
# Displaying bitmaps

Opisane dokładnie to co chcesz zrobić, nawet na przykładzie kulek.
 

Tomaj

Tomaj

Użytkownicy
posty107
Propsy13
  • Użytkownicy
Wielkie dzięki za wszystko. Udało mi się nareszcie ruszyć z miejsca.
Temat do zamknięcia.

 


0 użytkowników i 1 Gość przegląda ten wątek.
0 użytkowników
Do góry