CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - DragAndDrop, TDragControlObject na TImage
Strona 1 z 1

DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: środa, 12 września 2012, 12:10
przez Mironas
Witam,
Drag&Drop za pomocą obiektu dziedziczącego po TDragControlObject. Do kursora myszki przyklejona jest grafika (ikona) symbolizująca przeciągany obiekt. Elementem docelowym jest TImage z wczytaną grafiką (grafika A).

Wszystko dobrze działa do momentu gdy w trakcie przeciągania zmienię w TImage grafikę A na inną (grafika B).
Wtedy:
1. Znika fragment ikony (D&D) znajdujący się nad Image (w trakcie Image1->Refresh() lub innych podobnych funkcji) aż do ponownego ruchu myszką.
2. Po ponownym ruchu myszki na obszarze Image który był przesłonięty ikoną pojawiają się fragmenty grafiki A (z przed zmiany).

O ile z problemem nr 1 można sobie poradzić (symulacja poruszenia myszką) to w kontekście punktu 2 jest to bez sensu.
Oczywiście Image1->Refresh() przywraca poprawną grafikę B ale powoduje zniknięcie ikony - i po ponownym ruchu myszki znowu pojawiają się błędy.

Czy ma ktoś pomysł jak w trakcie D&D poprawnie zmieniać grafikę pod przeciąganą ikoną? Komponentem docelowym nie musi być TImage.

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: środa, 12 września 2012, 16:25
przez Cyfrowy Baron
Mironas napisał(a): Do kursora myszki przyklejona jest grafika (ikona) symbolizująca przeciągany obiekt


A co to konkretnie jest?

Wszystko fajnie opisałeś, ale nie wiadomo co czym jest i w jaki sposób realizujesz to zadanie. Domyśle przy przeciąganiu to pod kursorem myszy niczego nie ma więc czym jest ta ikona, jak realizujesz zadanie drag and drop, w czym dokładnie tkwi problem?
Trochę kodu no i może jakiś prosty przykładowy program by można na własne oczy zobaczyć w czym tkwi problem.

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 10:10
przez Mironas
Załączam przykład (exe-ka i źródła z XE).

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 16:26
przez Cyfrowy Baron
Oto rozwiązanie Twojego problemu:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Image2DragOver(TObject *Sender, TObject *Source, int X, int Y,
          TDragState State, bool &Accept)
{
  Accept = true;
  int strona = (X < Image2->Width/2 ) ? 1 : 2;
  if ( Image2->Tag != strona )
  {
    Image2->Tag = strona;
    if ( strona == 1 )
      Image2->Picture->Bitmap->Assign( Image3->Picture->Bitmap );
    else
          Image2->Picture->Bitmap->Assign( Image4->Picture->Bitmap );


  }

  Image2->Invalidate(); /* dokładnie tutaj poza warunkiem */
}

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 16:57
przez Mironas
Cyfrowy Baron napisał(a):Image2->Invalidate(); /* dokładnie tutaj poza warunkiem */

Ale to powoduje schowanie się grafiki przy kursorze pod Image2. Na dodatek przy każdym poruszeniu myszką grafika jest odrysowana i ponownie chowa się pod Image2, co powoduje nieprzyjemne migotanie.
Gdyby po Invalidate() dało się odświeżyć przeciąganą grafikę to może problem byłby rozwiązany.

Próbowałem na czas odrysowania Image2 ukryć przeciąganą grafikę ale nie wiem jak to zrobić. To nie działa:
KOD cpp:     UKRYJ  
  FDragObject->AlwaysShowDragImages;    // <- to jest 'false'
  FDragObject->HideDragImage();
  [...]
  FDragObject->ShowDragImage();
 

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 17:30
przez Cyfrowy Baron
Umieść funkcję Invalidate w zdarzeniu OnDragDrop:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Image2DragDrop(TObject *Sender, TObject *Source, int X, int Y)
{
   Image2->Invalidate();
}


I po problemach.

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 17:44
przez Mironas
Chyba mnie nie rozumiesz. Chodzi o sytuacje kiedy jeszcze przeciągam obiekt nad Image2 ale go jeszcze nie upuściłem. W zależności od pozycji myszki na Image2 chcę zmieniać grafikę w Image2 (zaznaczanie wskazanych fragmentów) i jednocześnie mieć poprawnie wyświetloną grafikę przyklejoną do myszki (ponad Image2).

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 18:45
przez Cyfrowy Baron
Ależ rozumiem, ale nie można mieć wszystkiego. Grafika przyklejona do myszki wyświetla się prawidłowo, gorzej jednak z grafiką w Image2, gdyż dopóki nie puścisz myszki wyświetla się nieprawidłowo, czyli obszar przesłonięty przez grafikę podczepioną do myszki w Image2 zawiera obraz poprzedniej grafiki. Niestety wynika to z niedoskonałości klasy TImage, ale testy z innymi obiektami też wypadają kiepsko.

Będzie dobrze jak przerzucisz kod do zdarzenia OnDragDrop, ale jak rozumiem chcesz mieć możliwość podglądu tego co ma wpaść do Image2, więc to odpada.

Niestety nie widzę sposobu w jaki można by ten problem rozwiązać.

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 18:59
przez Mironas
A więc pozostaje mi porzucić TDragControlObject i zrobić podgląd przeciąganej grafiki za pomocą dodatkowego okna (TForm) z ustawionym AlfaBlend. Ma to jednak dodatkowe wady - przeźroczystość jest jednolita dla całego okna i nawet jeśli umieszczę na nim Image z PNG z obszarami o różnej przeźroczystości to 'pod spodem' będzie widać kolor okna. Nawet TransparentColor tego nie załatwi.

Cóż, dzięki za zainteresowanie i za poświęcony czas. Pozdrawiam.

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 19:10
przez Cyfrowy Baron
Mironas napisał(a):to 'pod spodem' będzie widać kolor okna.


Niekoniecznie! Ustaw kolor przeźroczysty dla formularza w jego właściwości TransparentColorValue i włącz przeźroczystość okna ustawiając właściwość TransparentColor na true. Następnie zmień kolor okna na ten sam który ustawiłeś w jego właściwości TransparentColorValue. W ten sposób okno będzie całkowicie przeźroczyste, a AlphaBlend będzie odnosić się tylko do obiektów na oknie.

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 20:37
przez Mironas
Ustaw kolor przeźroczysty dla formularza w jego właściwości TransparentColorValue i włącz przeźroczystość okna ustawiając właściwość TransparentColor na true. Następnie zmień kolor okna na ten sam który ustawiłeś w jego właściwości TransparentColorValue.

Niestety takie rozwiązanie jest mocno niedoskonałe. Już wcześniej pisałem że 'TransparentColor tego nie załatwi'. A konkretnie to:

1. Przeźroczystość PNG będzie prawidłowa tylko dla obszarów gdzie alfa=0 lub alfa=255. Dla innych wartości uzyskamy kolor z PNG zmieszany z kolorem formy, a więc inny niż TransparentColorValue, a więc nieprzeźroczysty. Przykładowo jeśli kolor formy oraz TransparentColorValue ustawię na clWhite, a na PNG będę miał obszar cienia (ciemny kolor z alfa=50) to pod nim będzie widać białe tło.

2. Jeśli przypadkiem zdarzy się że na PNG będzie nieprzeźroczysty obszar o identycznym kolorze jak TransparentColorValue to zrobi się w tym miejscu dziura. Można oczywiście dać jakiś dziwny kolor dla TransparentColorValue ale to nie daje gwarancji.

Dlatego uważam że najrozsądniej będzie odpuścić sobie TransparentColor, ustawić kolor okna na biały i AlphaBlend na około 128. Będzie zawsze widoczne białe tło pod miniaturą ale trudno, nic lepszego nie wymyślę.

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: czwartek, 13 września 2012, 23:21
przez Gnusznak
Mironas napisał(a):Chyba mnie nie rozumiesz. Chodzi o sytuacje kiedy jeszcze przeciągam obiekt nad Image2 ale go jeszcze nie upuściłem. W zależności od pozycji myszki na Image2 chcę zmieniać grafikę w Image2 (zaznaczanie wskazanych fragmentów) i jednocześnie mieć poprawnie wyświetloną grafikę przyklejoną do myszki (ponad Image2).


Niestety nie będę wstanie pomóc, ale Twój program działa u mnie poprawnie i grafika w Image2 jest wyświetlana prawidłowo pod Image1. Próbowałem na wiele sposobów przeciągać, potrząsać kursorem myszy nad Image2 i cały czas Image1 jest półprzeźroczyste, a Image2 zmienia się i odrysowuje prawidłowo :)

Re: DragAndDrop, TDragControlObject na TImage

Nowy postNapisane: piątek, 14 września 2012, 04:49
przez Cyfrowy Baron
To wynika prawdopodobnie z tego, że ty sprawdzałeś pogram w systemie Vista a my w Windows XP.