[C++] Maska dla TImage

0

Czy ktoś mogłby podać jakiś link, albo napisać coś o tym jak zrobić maskę dla obrazka. Chodzi mi o uzystkanie takiego efektu jakbym miał GIF połprzeźroczysty.
Czyli jeden obrazek jest normalny a drugi ma 2 kolory i pierwszy jest wycinany wg wzoru jaki znajduje się na obrazku drugim (masce).

0

Wystarczyło poszukać w pomocy i masz:

  Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
  try
  {
    pBitmap->LoadFromFile("C:\\Program Files\\Common Files\\Borland Shared\\Images\\Splash\\256color\\factory.bmp ");
    pBitmap->Transparent = true;
    pBitmap->TransparentColor = pBitmap->Canvas->Pixels[50,50];
    Form1->Canvas->Draw(0,0,pBitmap);
    pBitmap->TransparentMode = tmAuto;  
    Form1->Canvas->Draw(50,50,pBitmap);
  }
  catch (...)

  {
    ShowMessage("Could not load or display bitmap");
  }
  delete pBitmap;

0

Troche nie łapie tego kodu?
Zresztą nie działa mi coś dostaje błąd:
[C++ Error] Unit1.cpp(22): E2193 Too few parameters in call to '_fastcall TCanvas::GetPixel(int,int)'
Cały kod wyglada tak:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
void main();
{
try
  {
    pBitmap->LoadFromFile("C:\\Program Files\\Common Files\\Borland Shared\\Images\\Splash\\256color\\factory.bmp ");
    pBitmap->Transparent = true;
    pBitmap->TransparentColor = pBitmap->Canvas->Pixels[50,50];
    Form1->Canvas->Draw(0,0,pBitmap);
    pBitmap->TransparentMode = tmAuto;
    Form1->Canvas->Draw(50,50,pBitmap);
  }
  catch (...)

  {
    ShowMessage("Could not load or display bitmap");
  }
  delete pBitmap;
}

}

Pewnie coś pomieszałem :(

0

Spróbuj tak:

...
 pBitmap->TransparentColor = pBitmap->Canvas->Pixels[50][50];
...
0

no już nie ma błędów ale niestety nic się na formie nie pokazuje

0
<sup napisał(a)

saint</sup>>no już nie ma błędów ale niestety nic się na formie nie pokazuje

A tą ścieżkę zmieniłeś chociaż?

0

dlaczego mam ja zmieniac przeciez jest dobra

0

Uuuuu dopiero zauważyłem :|

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); //<--- dlaczego to tutaj jest????
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
void main(); //<--- a to po co???????
{
try
  {
    pBitmap->LoadFromFile("C:\\Program Files\\Common Files\\Borland Shared\\Images\\Splash\\256color\\factory.bmp ");
    pBitmap->Transparent = true;
    pBitmap->TransparentColor = pBitmap->Canvas->Pixels[50,50];
    Form1->Canvas->Draw(0,0,pBitmap);
    pBitmap->TransparentMode = tmAuto;
    Form1->Canvas->Draw(50,50,pBitmap);
  }
  catch (...)

  {
    ShowMessage("Could not load or display bitmap");
  }
  delete pBitmap;
}

}

Nie widać obrazka bo całość jest w konstruktorze - okno w tym czasie nie jest widoczne. Przenieś ten przykład, który podałem ci na początku do jakiegoś handler'a np.

OnPaint

.

0

Więc wygląda to tak:
CPP

//---------------------------------------------------------------------------

#include <vcl.h>
#include <string.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
int HovDir=1;                // <- to musi tutaj byc inaczej wogole nie działa
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void Route(int x)
{
String nr;
nr=(IntToStr(x));
  try
  {
    pBitmap->LoadFromFile("D:\\Hover Racer\\gfx\\"+nr+".bmp");
    pBitmap->Transparent = true;
    pBitmap->TransparentColor = pBitmap->Canvas->Pixels[1][1];
    //Form1->Canvas->Draw(0,0,pBitmap);
    pBitmap->TransparentMode = tmAuto;
    Form1->Canvas->Draw(30,30,pBitmap);
  }
  catch (...)
  {
    ShowMessage("Could not load or display bitmap");
  }
  delete pBitmap;
}
//----------------------------------------------------------------------


void __fastcall TForm1::OnKeyDown(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
        if(Key == VK_LEFT)
        {
            //ShowMessage("You pressed LEFT");
            HovDir=((HovDir-1)%16);
            if(HovDir==0)
            HovDir=16;
            Route(HovDir);

        }
        if(Key == VK_RIGHT)
        {
            //ShowMessage("You pressed RIGHT");
            HovDir=((HovDir+1)%16);
            if(HovDir==0)
            HovDir=1;
            Route(HovDir);
        }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Paint(TObject *Sender)
{
try
  {
    pBitmap->LoadFromFile("D:\\Hover Racer\\gfx\\1.bmp");
    pBitmap->Transparent = true;
    pBitmap->TransparentColor = pBitmap->Canvas->Pixels[1][1];
    //Form1->Canvas->Draw(0,0,pBitmap);
    pBitmap->TransparentMode = tmAuto;
    Form1->Canvas->Draw(30,30,pBitmap);
  }
  catch (...)
  {
    ShowMessage("Could not load or display bitmap");
  }
  delete pBitmap;        
}
//---------------------------------------------------------------------------

H

//---------------------------------------------------------------------------

#ifndef Unit3H
#define Unit3H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
        void __fastcall OnKeyDown(TObject *Sender, WORD &Key,
          TShiftState Shift);
        void __fastcall Paint(TObject *Sender);
private:	// User declarations
public:		// User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

No niestety dostaje taki błąd:
[C++ Error] Unit3.cpp(45): E2316 '_fastcall TForm1::OnKeyDown(TObject *,unsigned short &,TShiftState)' is not a member of 'TForm1'

Co jest dość dziwne bo mam drugi program w którym mam tak samo zadeklarowane OnKeyDown w CPP i w H i tam jakoś działa ????????

0

OK. Co do zmiennych:

 ...
Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
int HovDir=1;                // <- to musi tutaj byc inaczej w ogóle nie działa
...

To nie musi tutaj być ;). Owszem to jest poprawnie ale byłoby schludniej i zgodnie z pewnymi zasadami (m.i kontrola dostępu) gdyby te zmienne były składowymi klasy. I tak w sekcji private deklarujesz:

class TForm1 : public TForm
{
__published:
  ...
  ...
private:
  Graphics::TBitmap *pBitmap;
  int HovDir;
public:
        __fastcall TForm1(TComponent* Owner);
        __fastcall ~TForm1();
};

w konstruktorze inicjujesz (jeżeli jest taka potrzeba):

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
  pBitmap = new Graphics::TBitmap();
  HovDir=1;
}

a w destruktorze zwalniasz pamięć (jeżeli jest taka potrzeba):

__fastcall TForm1::~TForm1()
{
  delete pBitmap;
}

Dalej... Funkcja Route. Zwalniasz w niej globalny obiekt

TBitmap

, który jest tylko raz tworzony, a funkcja wywoływana jest kilka razy w programie - co to oznacza to chyba nie musze mówić ;)

void Route(int x)
{
  ....
  delete pBitmap; //<--- !!!!!!!!!!!!!!!!!!!!!!!!!
}

To samo funkcja Paint.

No niestety dostaje taki błąd:
[C++ Error] Unit3.cpp(45): E2316 '_fastcall TForm1::OnKeyDown(TObject *,unsigned short &,TShiftState)' is not a member of 'TForm1'

Co jest dość dziwne bo mam drugi program w którym mam tak samo zadeklarowane OnKeyDown w CPP i w H i tam jakoś działa ????????

Z tego co pamiętam to BCB 1.0 miał takie akcje :/ Czasami pomaga usunięcie plików *.obj w projekcie i przekompilowanie całości od nowa (Build All)

0

Niestety wywalenie *.obj nie pomogło :|

0

Jeszcze jedna mała sprawa całość na razie mi działa, chciałbym stworzyć efekt animacji (ruchu/przesuwania) tego półprzeźroczystego obrazka kod jest prosty:

for(i=0;i<50;i++)
{
        Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
        pBitmap->LoadFromFile("D:\\Hover Racer\\gfx\\hover\\1.bmp");
        pBitmap->Transparent = true;
        pBitmap->TransparentMode = tmAuto;
        Form1->Canvas->Draw(20+i,20+i,pBitmap);
        Sleep(50);
        delete pBitmap;
}

I teraz problem w tym że myślałem że delete'em skasuje starą Bitmape a potem stowrze nową o 1pixel dalej niestety ten delete jakoś nie działa :/
Jak to napisać żeby było ok???

0

I teraz problem w tym że myślałem że delete'em skasuje starą Bitmape a potem stowrze nową o 1pixel dalej niestety ten delete jakoś nie działa
Jak to napisać żeby było ok???

Pytanie brzmi: a po co ją usuwasz? przecież pozycję bitmapy ustalasz w funkcji

TCanvas::Draw

. Funkcja ta kopiuje bitmapę w odpowiednie miejsce (w tym przypadku) na formie. Kod, który napisałeś jest przykładem tego jak programować się nie powinno ;). Tu masz wersję poprawioną. Porównaj ją ze swoją i wyciągnij wnioski (jeśli cię takowe interesują ;)).

Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
pBitmap->LoadFromFile("D:\\Hover Racer\\gfx\\hover\\1.bmp"); //<--- ja uważałbym z tymi ścieżkami ustawionymi na 'sztywno'
pBitmap->Transparent = true;
pBitmap->TransparentMode = tmAuto;

for(int i=0;i<50;i++)
{
  Form1->Canvas->Draw(20+i,20+i,pBitmap);
  Sleep(50);
} 

delete pBitmap;

PS. oczywiście tą pętle możnaby nieco bardziej zoptymalizować ale.... co tam :P

0

Dzięki kod jest naprawdę fajny szkoda tylko że problem pozostał a stare obrazki nie znikają :-|

0
<sup napisał(a)

saint</sup>>Dzięki kod jest naprawdę fajny szkoda tylko że problem pozostał o stare obrazki nie znikają :-|

Sprawa wydawałoby się prosta - musisz przed narysowaniem następnej pozycji bitmapy odmalować tło. I tu możesz użyć przed wywołaniem

TCanvas::Draw

metody TForm::Invalidate()

 lub <code class="cpp">TForm::Update()
...
...
for(int i=0;i<50;i++)
{
  Form1->Update(); 
  Form1->Canvas->Draw(20+i,20+i,pBitmap);
  Sleep(50);
}

tyle, że na 90% animacja będzie błyskać:/ Druga metoda to zastosowanie podwójnego buforowania. Informacji na jego temat poszukaj na forum/w internecie ;)

0

Niestety Update nic nie daje :/ stare obrazki nie znikaja

0

Użyj

TForm::Repaint()

i zacznij w końcu czytać dokumentację!!!

0

Czytam dokumentacje i szukam w google ale jakoś nie moge znalezc nic konkretnego, a przy tym repaint mi tylko się całość zapętla i po wykonaiu petli jest ona wykonywana od nowa, czyli w sumie to przrysowuje ale tak troche glupio bo poporstu tak jakbym pusczał program jeszcza raz.

Może powiem jak to wygląda. Mam pBitmap i pBitmap2, pBitmap2 jest tłem i jest tworzona jako pierwsza pozniej nie niej jest tworzona pBitmap czyli moj obrazek który ma się przesuwać a raczej być przerysowywany o 1px co ileśtam ms a stary obrazek ma znikać. Dodatkowo ta przesuwana Bitmap'a ma w dalszym stadium programu się zmieniać tzn. ma do niej być załadowany inny obrazek (1 z 16).

0

Czytam dokumentacje i szukam w google ale jakoś nie moge znalezc nic konkretnego

To coś słabo czytasz tudzież szukasz :P

[...] a przy tym repaint mi tylko się całość zapętla i po wykonaiu petli jest ona wykonywana od nowa

Bo jeśli ta procedura jest w handlerze

OnPaint

to nic dziwnego. Między innymi dlatego Invalidate()

 nie działa jak trzeba ;) Użyj timer'a.


> Może powiem jak to wygląda. Mam pBitmap i pBitmap2, pBitmap2 jest tłem i jest tworzona jako pierwsza pozniej nie niej jest tworzona pBitmap czyli moj obrazek który ma się przesuwać a raczej być przerysowywany o 1px co ileśtam ms a stary obrazek ma znikać

Zrób inaczej. W konstruktorze załaduj wszystkie bitmapy, które będą  wykorzystywane w programie. Czyli 
```cpp
pBitmap
tło, pBitmap1</li> </ul>
 - obrazek 1,..., <code class="cpp">pBitmapN
obrazek N. Tworzysz jeszcze dodatkową (pustą) bitmape pBackBitmap</li> </ul>
 i ustawiasz jej rozmiar na taki, jaki jest obszar rysowania twojej animacji. Teraz podczas rysowania każdej fazy animacji robisz tak:

1 - kopiujesz do 
```cpp
pBackBitmap

tło (pBitmap

).
2 - kopiujesz do 
```cpp
pBackBitmap

któryś z obrazków pBitmap1

... <code class="cpp">pBitmapN

(oczywiście w odpowiednie miejsce)
3 - kopiujesz

pBackBitmap

do kontekstu okna.

Gwoli ścisłości. Do kopiowania używasz funkcji

TCanvas::Draw

;)

0

Mam problem z tym rysowaniem :/ Rysowanie TBitmap działa mi tylko jak jest w funkcji OnPaint jak ten sam kod przełoże do jakiejś nowej funkcji to już się nic nie rysuje? Jak zrobić żebym rysuwanie działało w innej funkcji.

String StrHovDir;
Graphics::TBitmap *pHover = new Graphics::TBitmap();
Graphics::TBitmap *pMap = new Graphics::TBitmap();
StrHovDir=IntToStr(HovDir);

  pMap->LoadFromFile("D:\\Hover Racer\\gfx\\map\\map1_v.bmp");
  Form1->Canvas->Draw(0,0,pMap);
  pHover->LoadFromFile("D:\\Hover Racer\\gfx\\hover\\"+StrHovDir+".bmp");
  pHover->Transparent = true;
  pHover->TransparentMode = tmAuto;
  Form1->Canvas->Draw(sX-25,sY-25,pHover);
  ShowMessage(StrHovDir);

^^ Kod jest taki jak go wstawie do OnPaint to jest ok ale jak do innej funkcji to juz nie działa :-|

0

Co nie działa? nie kompiluje się? Gdzie tą procedurę wstawiłeś? Problem w tym, że ty nie rozumiesz mechanizmu rysowania w oknie :/

0

Napisałem przecież ze jak ten kod jest w OnPaint to działa i rysuje ale takie coś mi nie odpowiada bo musze te rysowanie miec w osobnej funkcji ale jak dam jed do osobnej funkcji np:
void Drawing()
{
...Ten kod co wczesniej...
}

to już się nic nie rysuje nie ma żadnych błędów wszystko się kompiluje ale na formie nic sie nie rysuje

0

Rozumiem, że pisząc:

void Drawing()
{
...Ten kod co wczesniej...
}

masz na myśli:

void TForm1::Drawing()
{
...Ten kod co wczesniej...
}

Napisałem przecież ze jak ten kod jest w OnPaint to działa i rysuje ale takie coś mi nie odpowiada bo musze te rysowanie miec w osobnej funkcji ale jak dam jed do osobnej funkcji [...] to już się nic nie rysuje

No dobra, masz funkcje

void TForm1::Drawing()

i gdzie ją umieściłeś (chodzi o wywołanie)? Są dwie opcje: w funkcji OnPaint

 i w jakimś handlerze timer'a np. <code class="cpp">OnTimer

. W przypadku animacji opcja z timer'em wydaje się najsensowniejsza ;)

0

Ok już wszystko śmiga jedyny problem to to że jak rysuje ciagle na formie to mi się pamięć zajmuje i po chwili mam komunikat za mało pamięci wirtualnej.
Więc dedukuje że źle myslałem i jednak ciagłe przerysowywanie Bitmapy na forme zawala pamięć, więc teraz jak kasować taka narysowana Bitmape?? chodzi o to że pod obiektem który się przesuwa (przerysowuje) jest 2ga Bitmapa nieruchoma (tło) i żeby nie było widać poprzednich położeń przesuwanej Bitmapy przerysowywałem też to tło jednak to zły pomysł. No więc jak usunać narysowana na Formie Bitmape? ewentualnie wszystko co jest na Formie narysowane?

0

Więc dedukuje że źle myslałem i jednak ciagłe przerysowywanie Bitmapy na forme zawala pamięć, więc teraz jak kasować taka narysowana Bitmape??

Źle dedukujesz :D Taka bitmapa jest kopiowana do pamięci ekranu. Jak już wcześniej pisałem, nie znasz mechanizmów rysowania okien tudzież w oknach. Poszukaj informacji na ten temat (o ile cię to interesuje) bo bez minimum tej wiedzy cały czas będziesz działał po omacku i wymyślał jakieś dziwne teorie ;) Tu masz link gdzie znajdziesz podstawowe informacje.

[...] problem to to że jak rysuje ciagle na formie to mi się pamięć zajmuje i po chwili mam komunikat za mało pamięci wirtualnej.

Sprawdź, czy wszystkie stworzone przez ciebie obiekty są zwalniane.

1 użytkowników online, w tym zalogowanych: 0, gości: 1