2010-11-07 12 views
10

Ho trovato questa domanda su StackOverflow. Fondamentalmente, l'utente voleva disegnare pulsanti personalizzati sulla barra del titolo.Disegna i pulsanti personalizzati su Windows Vista/7 Barra titolo Aero

Ho provato il codice e ho realizzato che funziona in vista/7 solo quando Aero è disabilitato. La mia domanda è, c'è un modo per disegnare pulsanti personalizzati sulla barra del titolo mentre è abilitato?

Inoltre, esiste un modo per leggere le informazioni dal tema corrente in modo da poter applicare uno stile ai pulsanti per abbinarli a quelli già esistenti.


Aggiornamento

Ecco uno screenshot dal mio computer a dimostrazione del concetto di cui sopra. Ho ottenuto i pulsanti della barra del titolo aggiuntivi dopo aver installato DisplayFusion.
Notepad2 showing additional buttons.

E so che DisplayFusion è un programma .NET perché si apre in .NET Reflector. Il lato negativo è che il programma è offuscato. Non come volevo decompilare il programma o altro; Voglio solo aggiungere un pulsante alla mia barra del titolo per fare qualcos'altro (come minimizzare sulla barra delle applicazioni, per esempio).
Di seguito è riportato lo screenshot, a dimostrazione del fatto che il programma è un'applicazione .NET.
.NET Reflector showing DisplayFusion

+0

Dimentica questo, non funziona più. –

+4

So che è possibile perché c'è questa app multi monitor chiamata ** Display Fusion ** che fa proprio questo. So che è un'app .NET perché l'ho guardata con .NET Reflector di Lutz Roeder. –

risposta

4

Finché siete disposti a ridisegnare l'intero contenuto della barra del titolo, quindi è possibile utilizzare il metodo DwmExtendFrameIntoClientArea del API DWM, che comporta la definizione di finestra non avere barra del titolo, permettendo al DWM per disegnare il suo vetro nella tua area utilizzabile per creare un nuovo spazio che assomigli alla barra del titolo ma che sia in realtà nella tua area client, in modo che tu possa disegnare pulsanti su di esso.

Lo svantaggio di questo metodo è che dovrete fare i pulsanti standard se li volete. Riduci a icona, Ingrandisci e Chiudi non sono un problema da ricreare (anche se scoprirai che il pulsante di ingrandimento è un pulsante di disattivazione con aspetto basato sullo stato), ma potresti trovare il problema con la ricreazione del pulsante in alto a sinistra. Dovrai anche ridisegnare il tuo titolo, ovviamente, ma non riesco a immaginare che avrai qualche problema con questo.

Per quanto riguarda la lettura dei dati del tema corrente per restyling dei pulsanti come loro, mi dispiace ma non ne so nulla. Il mio suggerimento sarebbe quello di usare la trasparenza quando si costruiscono i pulsanti sulla barra del titolo e di usare effetti di luce traslucidi, eccetera. In questo modo sarai in grado di conservare lo sfondo di vetro e modificarne semplicemente l'aspetto sovrapponendo un colore traslucido. Inoltre, se lo fai in questo modo, lo spostamento delle luci speculari sul vetro si muoverà naturalmente, mentre se hai semplicemente i loro colori a tema potresti trovare che non hai avuto accesso alle loro riflessioni o che hanno ricreato di nuovo all'interno lo spazio dei tuoi pulsanti. Solo i miei due centesimi, ovviamente - se riesci a trovare un modo per fare i tuoi colori a tema eccetera, con tutti i mezzi.

C'è un avvertimento a questo però - c'è un altro thread StackOverflow (http://stackoverflow.com/questions/2666979/net-framework-4-0-and-drawing-on-aero-glass-issue/4656182# 4656182) che sta descrivendo un problema con il metodo DwmExtendFrameIntoClientArea dell'API DWM, quindi se fossi in te, lo leggerei prima di provare questa soluzione.

4

Ho fatto qualche ricerca in questo come ho implementato anche questo nella mia soluzione multi-monitor. Il modo in cui DisplayFusion e TeamViewer lo hanno implementato è la sovrapposizione di un modulo personalizzato sulla finestra desiderata contenente i pulsanti. Puoi usare Spy ++ per confermare questo.

Questa è l'idea generale:

  1. Scrivi un gancio DLL per ottenere una notifica quando viene creata una finestra, rimosso, attivato, riposizionata o ridimensionata.
  2. Crea un modulo trasparente utilizzando il tasto di trasparenza o utilizzando questo alpha-PNG and GDI+ solution e simula il/i pulsante/i dipingendolo da solo.
  3. Durante la creazione/rimozione della finestra si mostra/nasconde il modulo del barra del titolo per le finestre desiderate.
  4. Sui messaggi di ridimensionamento/riposizionamento della finestra riallineare il modulo del barra del titolo.
  5. Attivando la finestra si imposta la posizione Z della finestra in modo che si trovi sopra la finestra desiderata.

Come ottenere e impostare la posizione Z tramite le API GetWindow e SetWindowPos.
Tenere presente che la DLL deve essere scritta in una lingua nativa. Tuttavia si van usare qualcosa di simile per aggirare questo problema: Using Window Messages to Implement Global System Hooks in C#

Ed ecco il mio risultato:

enter image description here

+0

La tua soluzione sembra promettente. Ho capito come creare la forma trasparente e rilevare l'apertura, lo spostamento e la chiusura di Windows. Quello che mi piacerebbe sapere è come si creano i pulsanti a tema vuoto in modo da poter dipingere il mio. Se possibile, puoi caricare la tua soluzione? –

+0

Puoi inserire qualche codice per mostrare come hai creato i pulsanti della barra del titolo nello screenshot? –

+0

@Jelle Vergeer Si prega di considerare di aggiungere un collegamento per il codice sorgente del "risultato", ho bisogno di questa soluzione ... +1 – ElektroStudios

0

Ok, ganci di sistema sono l'approccio diretto per ottenere informazioni sulle posizioni delle finestre modificati e La proposta Jelle's con modulo trasparente è molto buona. Ma è possibile utilizzare un metodo meno invasivo per ottenere informazioni sul desktop di Windows utilizzando user32.dll

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect); 

La finestra gestisce si può ottenere usando EnumDesktopWindows

[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", 
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam); 

Un esempio di questo si può ottenere dal thread getting-a-list-of-all-applications-in-c-sharp