TrayIcon & Position



  • www.codeproject.com ist kein Artikel! Gib den bitte nochmal mit einem vollständigen Link an. Danke.



  • WebFritzi schrieb:

    www.codeproject.com ist kein Artikel! Gib den bitte nochmal mit einem vollständigen Link an. Danke.

    ich glaub er meint den link von der ersten seite http://www.codeproject.com/shell/trayposition.asp



  • Es geht ich kann die Position jetzt 100% genau herausfinden

    Verrätst du (später) noch wie das geht?

    Weil gestern hattest du ja geschrieben, das du es heute erläuterst. 😃



  • Hä? Das ist doch nur Fenstergefriemel da im Artikel. Das hat nichts mit der Position eines TrayIcons zu tun.
    Ich habe mir folgendes gedacht: Am Anfang ist das TrayIcon ja ganz links angeordnet. Es könnte ja nun sein, dass man eine Nachricht bekommt, wenn sich das Icon verschiebt. 😕



  • WebFritzi schrieb:

    Hä? Das ist doch nur Fenstergefriemel da im Artikel. Das hat nichts mit der Position eines TrayIcons zu tun.

    Der Meinung bin ich auch 😃

    WebFritzi schrieb:

    Es könnte ja nun sein, dass man eine Nachricht bekommt, wenn sich das Icon verschiebt.

    Dem ist nicht so 😡

    Ich hab nur den Ansatz verwendet:

    if (_tcscmp(szClassName, _T("TrayNotifyWnd")) == 0)
    

    Warum der Mensch dann auf einmal so ein Bockmist macht weiß ich auch nicht. 😃

    Dann hol ich mir das Handle von dem Kasten wo die Uhr und die Symbole drin sind.

    Dann das Handle der Toolbar die in dem Kasten is und wenn man das hatt kann man fast auf die button zugreifen.

    Nun muss man nur noch ne RECT var im Adressraum des Explorers Allocieren.
    Dann Message an Toolbar Getbuttonrect oder so, Toolbar schreibt das Ergebniss in die RECT var im Speicher des Explorers und die klau ich ihm dann.
    So kann man alle Messages an das Control Toolbar ausführen.

    Wenn ihr wollt kann ich ja nochmal den kompletten Quelltext posten.

    Mfg TheBender



  • TheBender schrieb:

    Warum der Mensch dann auf einmal so ein Bockmist macht weiß ich auch nicht. 😃

    Weil er davon ausgeht, dass die Windows mit der Entwicklung von Windows andere Klassennamen bekommen. Oder so ähnlich...

    TheBender schrieb:

    Dann hol ich mir das Handle von dem Kasten wo die Uhr und die Symbole drin sind.

    Klar. OK.

    TheBender schrieb:

    Dann das Handle der Toolbar die in dem Kasten is und wenn man das hatt kann man fast auf die button zugreifen.

    Oh, sehe ich grade zum ersten mal, dass das ne ToolBar ist. Kann es sein, dass das bei Win98 noch anders war? Könnte da evtl. mal jemand nachschauen?

    TheBender schrieb:

    Nun muss man nur noch ne RECT var im Adressraum des Explorers Allocieren.

    DAS würde mich interessieren, wie du das machst.

    TheBender schrieb:

    Dann Message an Toolbar Getbuttonrect oder so, Toolbar schreibt das Ergebniss in die RECT var im Speicher des Explorers und die klau ich ihm dann.
    So kann man alle Messages an das Control Toolbar ausführen.

    Aha. Und woher weißt du dann, welches DEIN Icon ist?

    TheBender schrieb:

    Wenn ihr wollt kann ich ja nochmal den kompletten Quelltext posten.

    Jo, das mit dem Adressraum würde mich auf jeden Fall interessieren. Danke.



  • WebFritzi schrieb:

    Weil er davon ausgeht, dass die Windows mit der Entwicklung von Windows andere Klassennamen bekommen. Oder so ähnlich...

    Würde wenig sinn machen weil die Klassennamen ja in der ComCtl definiert sind wenn ich dan ein Prog wie Word98 unter win2000 nich mehr gehen. Da wird schon für genug Abwärtskompatibilität gesorgt.

    WebFritzi schrieb:

    Oh, sehe ich grade zum ersten mal, dass das ne ToolBar ist. Kann es sein, dass das bei Win98 noch anders war? Könnte da evtl. mal jemand nachschauen?

    Ist sein Win95 und NT 4 schon so.

    TheBender schrieb:

    Nun muss man nur noch ne RECT var im Adressraum des Explorers Allocieren.

    DAS würde mich interessieren, wie du das machst.

    WebFritzi schrieb:

    TheBender schrieb:

    Dann Message an Toolbar Getbuttonrect oder so, Toolbar schreibt das Ergebniss in die RECT var im Speicher des Explorers und die klau ich ihm dann.
    So kann man alle Messages an das Control Toolbar ausführen.

    Aha. Und woher weißt du dann, welches DEIN Icon ist?

    Um rauszufinden welches icon meins ist gibt es zwei möglichkeiten:
    - Message TB_BUTTONCOUN und annehmen das der letzte button meiner ist, da ich ihr ja erst von ein paar ms hinzugefügt habe.
    - oder die bessere den button gleich mit der Message TB_ADDBUTTONS da hat man gleich ne ID.

    hier mein code

    RECT posICON;
    
    HWND hShellTrayWnd = FindWindow("Shell_TrayWnd", NULL);  //Taskleiste finden
    HWND hTrayNotifyWnd = FindWindowEx( hShellTrayWnd, NULL, "TrayNotifyWnd", NULL );  //Das rechte Kästel in der Taskleiste
    HWND hToolbarWindow32 = FindWindowEx( hTrayNotifyWnd, NULL, "ToolbarWindow32", NULL ); //Toolbar mit den Buttons
    
    if (hToolbarWindow32)
    {
        GetWindowRect( hToolbarWindow32, (LPRECT) &posICON );
        TCHAR szClassName[256];
        GetClassName( hToolbarWindow32, szClassName, 255 );
        OutputDebugString( szClassName );
    
        unsigned long pid;  //ProcessID
        HANDLE process;     //ProcessHandle
        GetWindowThreadProcessId( hToolbarWindow32, &pid ); //ProcessID holen
        process=OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, pid ); //ProcessHandle holen
    
        //Im Adressraum der "SHELL" Speicher für ein "RECT" allocieren
        RECT *_posICON = ( RECT* )VirtualAllocEx( process, NULL, sizeof( RECT ),    MEM_COMMIT, PAGE_READWRITE );
    
        //Speicher in "SHELL" beschreiben
        WriteProcessMemory( process, _posICON, &posICON, sizeof( RECT ), NULL );
    
        //Message an Toolbar (SHELL) ->Position des Button in "WPARAM", Adresse zur  Speicherung des RECT´s in "LPARAM"
        SendMessage( hToolbarWindow32, TB_GETITEMRECT, ( WPARAM ) 5, ( LPARAM ) _posICON );
    
        //Speicher in "SHELL" auslesen und in Localervariable speichern
        ReadProcessMemory( process, _posICON, &posICON, sizeof( RECT ), NULL );
    
        //allocierten Speicher im Adressraum der "SHELL" wieder freigeben
        VirtualFreeEx( process, _posICON, 0, MEM_RELEASE );
    
        //Koordinaten auf Desktopkoordinaten umrechnen
        MapWindowPoints( hToolbarWindow32, NULL, ( LPPOINT ) &posICON, 2 );
    }
    

    Ich werd das ganze noch in ne dll packen und alle function der Taskbar implementieren (Startmenü manipulieren, Schnellstart, Uhr und die normalen Button.
    Header wirds für C und Delphi geben.

    Mfg TheBender



  • Könntest du bitte nochmal genau erklären, was der Code so macht. Ich kapier's nämlich nicht so ganz. Wozu muss die RECT-Variable im Adressraum der Shell sein?



  • Ich nehme mal an, das liegt daran, dass TB_GETITEMRECT ja im Adressraum der Shell ausgeführt wird und du somit Speicher brauchst, der von dort aus gesehen gültig ist 😉



  • Wieso? Ich kann doch in GetWindowText() auch meinen eigenen Pointer aus meinem Prozess verwenden.



  • GetWindowText ist ja in user32.dll definiert. Die DLL ist im Adressraum von deinem Programm, somit kann sie auch dort schreiben. Wie jetzt user32.dll an den Namen kommt ist Sache von Windows und deren Handle-Verwaltung. Mit SendMessage wird die Nachricht direkt an das Fenster im fremden Prozess gechickt. Wenn das Fenster deinen Pointer nutzt greift es auf die Adresse im eigenen Adressraum zu.



  • OK, dann sach ich halt statt GetWindowText eben WM_GETTEXT. 😉 Wo ist da der Unterschied zu TB_GETITEMRECT?



  • WebFritzi schrieb:

    Wo ist da der Unterschied zu TB_GETITEMRECT?

    OK, ich gebe zu, ich weiß es nicht.
    Aber da mich das jetzt interessiert hab ich mal im Internet nachgeschaut. Windows behandelt manche Nachriten, unter anderem WM_GETTEXT (, WM_SETTEXT, WM_COPYDATA), anders, wenn diese Prozess-Grenzen überschreiten (um abwärtskompatibel zu den Real-Modus-Windows zu bleiben). Laut dieser Seite: http://www.mvps.org/vcfaq/sdk/16.htm regelt Windows das über Memory Mapped Files.
    Und in der Tat bekommt das fremde Fenster in meinem Test nicht die Adresse, die ich bei WM_GETTEXT in lParam übergebe, welch Überraschung. 😉



  • D@niel $chumann schrieb:

    Und in der Tat bekommt das fremde Fenster in meinem Test nicht die Adresse, die ich bei WM_GETTEXT in lParam übergebe, welch Überraschung. 😉

    Es war mir schon klar, dass der Text kopiert wird. Aber so könnte es sich doch auch mit der RECT-Struktur verhalten, oder?



  • Die Windowsentwickler werden sich schon was dabei gedacht haben, warum sie das nicht bei jeder Nachricht machen.
    Wen interessiert schon irgendeine RECT-Struktur von nem anderen Prozess -> so gut wie niemanden und da muss man Windows ja net noch mehr ausbremsen...
    bei WM_GETTEXT kann man es ja noch einigermassen verstehen (wahrscheinlich hat Microsoft irgendein Produkte, das WM_GETTEXT prozessübergreifend verwendet und das muss ja auch auf nem Protected-Mode-Windows noch laufen).



  • Eine Toolbar ist ein CommonControl. Die CommonControls werden, wie das auch bei eigenen Controls üblich ist, über Nachrichten des Typs WM_USER gesteuert:

    #define TB_GETITEMRECT          (WM_USER + 29)
    

    Woher soll Windows jetzt wissen, daß ein RECT kopiert werden muß? Es könnte doch auch sein:

    #define RB_GETBANDINFOA (WM_USER + 29)
    #define TTM_UPDATE              (WM_USER + 29)
    #define TBM_SETTOOLTIPS         (WM_USER+29)
    

    Wann ist jetzt RECT, wann nicht?



  • -King- schrieb:

    Woher soll Windows jetzt wissen, daß ein RECT kopiert werden muß?

    Na, das erkennt Windows wohl daran, dass die Message an eine ToolBar geschickt wurde.



  • WebFritzi schrieb:

    Na, das erkennt Windows wohl daran, dass die Message an eine ToolBar geschickt wurde.

    Bedenke, daß die Toolbar kein natives Control ist.



  • Meinst du mit "nativ" sowas wie Button & Co? Und was soll man da bedenken? Die Toolbar hat doch auch ihre eigene WindowProc, oder?



  • Natürlich hat auch die Toolbar eine WndProc. Und diese WndProc behandelt jetzt irgendwie die Nachricht (WM_USER + 29). Was da passiert, weiß das System natürlich nicht und kann deswegen auch nicht eingreifen. Anders sieht es bei WM_SETTEXT aus, da weißt Du sehr wohl vorher, was passiert.

    Mit native meine ich, daß die Toolbar nicht zum System gehört, sondern nur eine art AddOn ist. Schau Dir den von Dir angesprochenen Button an, der versteht 'echte' Nachrichten und nicht WM_USER. Z.B.:

    #define BM_GETCHECK        0x00F0
    

Anmelden zum Antworten