CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Własny kursor zamiast crHourGlass

Własny kursor zamiast crHourGlass

dział ogólny

Własny kursor zamiast crHourGlass

Nowy postprzez starjacker0 » piątek, 26 sierpnia 2011, 09:14

Laduje dwa kursory:
Kod: Zaznacz cały
WideString C_Path1 = ExtractFileDir(ParamStr(0)) + "\\data\\textures\\GUI\\Cursors\\sgs_cursor_1.cur"; //zwykły
WideString C_Path2 = ExtractFileDir(ParamStr(0)) + "\\data\\textures\\GUI\\Cursors\\sgs_cursor_2.ani"; //animowany
Screen->Cursors[1] = LoadCursorFromFile(C_Path1.c_bstr());
Screen->Cursors[2] = LoadCursorFromFile(C_Path2.c_bstr());
Form1->Cursor = TCursor(1);


Mam na formie ApplicationEvents.

Chcialbym cos takiego, aby zamiast kursora crHourGlass (w Win7 jest to kolko, w XP nie pamietam) pojawial sie moj kursor animowany, a potem (gdy normalnie pojawia sie crDefault) znow wrocil ten statyczny moj.
Niestety nie wiem, jak to zrobic; udaje mi sie tylko miec caly czas jeden, ale w zdarzeniach (gdy jest zajety program), w ktorych normalnie pojawia sie crHourGlass, ciagle jest windowsowy kursor zamiast mojego.
Prosze o pomoc.
Avatar użytkownika
starjacker0
Bladawiec
Bladawiec
 
Posty: 11
Dołączył(a): wtorek, 20 lipca 2010, 11:37
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: Windows 7 64-bit
Kompilator: C++ Builder 2010
Gadu Gadu: 0
    Windows 7Firefox

Re: Własny kursor zamiast crHourGlass

Nowy postprzez Cyfrowy Baron » piątek, 26 sierpnia 2011, 11:15

Gdy przypisujesz jakiś kursor do obiektu:

KOD cpp:     UKRYJ  
Form1->Cursor = TCursor(1);


To obiekt będzie używał tak długo jak tego nie zmienisz. Przykład zmiany kursora dla formularza:

KOD cpp:     UKRYJ  
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 String dir = ExtractFilePath(ParamStr(0));

 HCURSOR Kursor_1 = LoadCursorFromFile( (dir + "Kursor1.ani").c_str() );
 HCURSOR Kursor_2 = LoadCursorFromFile( (dir + "Kursor2.cur").c_str() );

 Screen->Cursors[1] = Kursor_1;
 Screen->Cursors[2] = Kursor_2;

 Form1->Cursor = (TCursor)1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 Form1->Cursor = (TCursor)2;
}


Jeżeli chcesz przywrócić kursor domyślny to przekazujesz wartość crDefault:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 Form1->Cursor = crDefault;
}


Jeżeli chcesz ustawić kursor dla całej aplikacji to zmieniasz kursor dla Screen a nie dla formularza:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 Screen->Cursor = (TCursor)2;
}


Przywracasz domyślny:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button4Click(TObject *Sender)
{
 Screen->Cursor = crDefault;
}


Z tym, że jeżeli zmieniłeś kursor domyślny dla formularza, to przywrócony zostanie ten domyślny, a nie systemowy. Jeżeli chcesz przywrócić systemowy zarówno dla ekranu (Screen) jak i dla formularza (Form1), to:

KOD cpp:     UKRYJ  
Form1->Cursor = crDefault;
Screen->Cursor = crDefault;


Jeżeli chcesz, żeby aplikacja używała Twojego kursora oczekiwania (IDC_WAIT) zamiast kursora systemowego gdy aplikacja jest zajęta, to najlepiej wywołać ten kursor za pomocą funkcji ::SetCursor

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

HCURSOR MY_WAIT; // <--

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 String dir = ExtractFilePath(ParamStr(0));

 MY_WAIT = LoadCursorFromFile( (dir + "aero_busy.ani").c_str() );

 HCURSOR Kursor_1 = LoadCursorFromFile( (dir + "Kursor1.ani").c_str() );
 HCURSOR Kursor_2 = LoadCursorFromFile( (dir + "Kursor2.cur").c_str() );

 Screen->Cursors[1] = Kursor_1;
 Screen->Cursors[2] = Kursor_2;

 Form1->Cursor = (TCursor)1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
 ::SetCursor( MY_WAIT );
 Sleep(5000); /* aplikacja zajęta */
}


Jeżeli po czasie gdy aplikacja była zajęta kursor nie powraca, to należy przywołać domyślny kursor w ten sposób:

KOD cpp:     UKRYJ  
 ::SetCursor( MY_WAIT );
 Sleep(5000); /* aplikacja zajęta */
 ::SetCursor(NULL);


Możesz też zmienić kursor dla całego systemu funkcją SetSystemCursor, ale można to zrobić tylko podczas uruchamiania aplikacji w konstruktorze klasy formularza i w trakcie działania programu nie da się tego kursora w systemie podmienić, ale można używać innych kursorów tak jak to opisałem wyżej. Zmiana kursora systemowego nie zmienia go na stałe, lecz tylko do czasu ponownego uruchomienia systemu. Systemu nie programu.

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#define OEMRESOURCE // WAŻNE!!!

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

HCURSOR MY_WAIT; // <--

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 String dir = ExtractFilePath(ParamStr(0));

 MY_WAIT = LoadCursorFromFile( (dir + "aero_busy.ani").c_str() );

 SetSystemCursor( MY_WAIT, OCR_WAIT); // <--

 HCURSOR Kursor_1 = LoadCursorFromFile( (dir + "Kursor1.ani").c_str() );
 HCURSOR Kursor_2;Kursor_2 = LoadCursorFromFile( (dir + "Kursor2.cur").c_str() );

 Screen->Cursors[1] = Kursor_1;
 Screen->Cursors[2] = Kursor_2;

 Form1->Cursor = (TCursor)1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
 ::SetCursor( LoadCursor(NULL, IDC_WAIT) ); /* funkcja wczyta podmieniony kursor systemowy */
 /* aplikacja zajęta */
 Sleep(5000);
 ::SetCursor(NULL);
}


Podmieniony kursor systemowy można przywrócić funkcją DestroyCursor, ale to działa tylko w odniesieniu do kursorów nie udostępnionych. Nie wiem o co dokładnie z tym chodzi:

KOD cpp:     UKRYJ  
DestroyCursor(MY_WAIT);



► patrz serwis: Cyfrowy Baron dział: porady -> różne: lub: spis wszystkich porad -> sekcja Kursor:

Porady:

Umieszczanie kursorów (*.cur, *.ani) w zasobach programu.
Wczytanie i używanie animowanego kursora.
Zmiana kursorów myszy dla całego systemu.




Jeżeli to nie rozwiązuje twoich problemów z kursorem to opisz problem w sposób bardziej zrozumiały.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Własny kursor zamiast crHourGlass

Nowy postprzez starjacker0 » sobota, 27 sierpnia 2011, 08:58

To:
Kod: Zaznacz cały
::SetCursor( MY_WAIT );

nie spelnia moich oczekiwan, gdyz nie wiem, jakie zdarzenie w aplikacji odpowiada za "zajetosc".

Z kolei podmiana kursora systemowego podmienia kursor zajetosci tak, jak chce, ale juz nie przywraca oryginalnego; a ja chce miec tylko i wylacznie wlasny kursor zajetosci w mojej aplikacji, a po jej zakonczeniu windowsowy.

Chodzi mi po prostu o cos takiego, ze gdy aplikacja jest zajeta i np. klikam w nia to pojawia sie ten kursor zajetosci (zwlaszcza przy obszernych petlach while).
W mojej aplikacji (z uzyciem OpenGL) mam funkcje wczytujaca tekstury, modele i tworzaca menu. Gdy klikam w forme, na ktorej pojawia sie ekran wczytywania, to pojawia sie kursor zajetosci (ale nie dlatego, ze ja go wywoluje w kodzie, tylko dlatego, ze aplikacja nie moze przetworzyc komunikatow, w tym przypadku klikniec, gdyz jest zajeta tym wczytywaniem - tak sadze, wiec oznajmia, ze jest zajeta).
Ja chce miec mozliwosc podmiany tego kursora zajetosci tak, aby tylko zmieniac jego wyglad (tylko w programie, aby po jego zakonczeniu w systemie juz go nie bylo), a nie jego moment wystepowania. Gdybym wiedzial, co to za zdarzenia obsluguja "zajętość" i jakiego komponentu uzyc, ktory to obsluguje (bo w ApplicationEvents probowalem i nie doszedlem do zadowalajacych efektow), to bym na poczatku zdarzenia zmienil kursor na moj animowany, a pod koniec przywrocil ten statyczny.
Nie mam zamiaru dawac tego kursora przez caly czas dzialania funkcji wczytujacej, gdyz zalezy mi tylko na modyfikacji samego wygladu kursorow w mojej aplikacji, a nie "miejsc" ich wystepowania.

Aplikacja wykonuje funkcje -> klikam -> pojawia sie kursor zajetosci (ale nie dlatego, ze ja tak chce, tylko aplikacja jest zajeta wykonywaniem tej obszernej funkcji) -> koniec wykonywania funkcji (wiec i przetworzenie oczekujacych komunikatow) -> kursor normalny
A ja chce tylko podmienic wyglad obu kursorow (statyczny - no problem, animowany dla zajetosci - juz mam problem).
Bestią jestem, by się bestią nie stać
Avatar użytkownika
starjacker0
Bladawiec
Bladawiec
 
Posty: 11
Dołączył(a): wtorek, 20 lipca 2010, 11:37
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: Windows 7 64-bit
Kompilator: C++ Builder 2010
Gadu Gadu: 0
    Windows 7Firefox

Re: Własny kursor zamiast crHourGlass

Nowy postprzez Cyfrowy Baron » sobota, 27 sierpnia 2011, 14:44

Istnieje pewien sposób na zmianę kursora za pomocą funkcji SetSystemCursor i przywrócenie go za pomocą tejże samej funkcji. Trzeba przed zmianą kursora dla całego systemu pobrać uchwyt do oryginalnego kursora systemowego a po zamknięciu aplikacji lub w dowolnym innym momencie przywrócić oryginalny kursor:
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
#define OEMRESOURCE

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"


HANDLE hWait;

HANDLE GetNoShareCursor(UINT ocr_id)
{
 HANDLE hCur = LoadImage(0, MAKEINTRESOURCE(ocr_id), IMAGE_CURSOR,
                                                   0, 0, LR_SHARED);
 if (!hCur) return 0;

 return CopyImage(hCur, IMAGE_CURSOR, 0, 0, 0);
}


TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) /* konstruktor klasy formularza */
        : TForm(Owner)
{
 String dir = ExtractFilePath(ParamStr(0));

 HCURSOR MY_WAIT = LoadCursorFromFile( (dir + "aero_busy.ani").c_str() );

 hWait = GetNoShareCursor(OCR_WAIT);
 SetSystemCursor(MY_WAIT, OCR_WAIT);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) /* zdarzenie OnClose */
{
   /* przywracamy oryginalny kursor */
   SetSystemCursor((HCURSOR)hWait, OCR_WAIT);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose) /* zdarzenie OnCloseQuery */
{
   /* przywracamy oryginalny kursor */
  SetSystemCursor((HCURSOR)hWait, OCR_WAIT);
}
//---------------------------------------------------------------------------
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Własny kursor zamiast crHourGlass

Nowy postprzez starjacker0 » niedziela, 28 sierpnia 2011, 08:59

Niestety ten sam efekt, czyli po wyjsciu z aplikacji moj kursor zajetosci zostaje (kodu podanego powyzej nie modyfikowalem nic, wiec nie popelnilem bledu).
Bestią jestem, by się bestią nie stać
Avatar użytkownika
starjacker0
Bladawiec
Bladawiec
 
Posty: 11
Dołączył(a): wtorek, 20 lipca 2010, 11:37
Podziękował : 2
Otrzymał podziękowań: 0
System operacyjny: Windows 7 64-bit
Kompilator: C++ Builder 2010
Gadu Gadu: 0
    Windows 7Firefox

Re: Własny kursor zamiast crHourGlass

Nowy postprzez Cyfrowy Baron » niedziela, 28 sierpnia 2011, 10:04

Testowałem ten kod w środowisku Windows XP 32bit i działa prawidłowo.

http://support.microsoft.com/kb/131991

W tej sytuacji pozostaje Tobie tylko jedno, w kodzie programu przed każdą dłuższą pętlą i przed każdym kodem powodującym wstrzymanie programu musisz wywołać funkcję ::SetCursor.

W OpenGL masz funkcję glutSetCursor która pozwala zmienić kursor myszy. W parametrze podajesz który kursor chcesz zmienić, dla kursora WAIT jako parametr podajesz GLUT_CURSOR_WAIT. Nie wiem o co dokładnie chodzi z tą funkcją, ale ona chyba tylko wywołuje kursor, niemniej jednak chyba istnieją jakieś funkcje w OpenGL, które pozwalają zdefiniować własne kursory, gdyż byłoby dziwne by akurat ten element gry był realizowany przez API systemu, a nie interfejs OpenGL. Poszukaj, ja o OpenGL nic nie wiem.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 5 gości