Form Aero Style   otázka

VB.NET, WinForms

Dobrý den,

rád bych se obrátil na Vás zkušenější s prosbou o pomoc ve snaze vylepšit záhlaví svých formulářů o možnost vkládání vlastních tlačítek a kreslení v neklientské oblasti např. záhlaví. Používám DWM (Desktop Window Manager) a pro rozšíření klientské oblasti funkci DwmExtendFrameIntoClientArea.

Nevím jak se dostat k informacím, které bych rád využil při vlastním vykreslení formuláře, např. jak získat barvu záhlaví formuláře a dokreslit pozadí rozšířené neklientské oblasti.

Set Form's Backcolor to Same Color as Current Aero Style Color :

https://social.msdn.microsoft.com/Forums...

Našel jsem tento odkaz, ale dostávám zpět modravé pozadí, ačkoli se ve skutečnosti záhlaví formuláře vykreslí v bělavé barvě, která nejspíš odpovídá SystemColors.ControlLightLight.

Jak se dostanu ke konkrétnímu stavu barvy záhlaví dle aktuálního stylu a téma v systému?

Použiji-li vlastní barvu, budu nucen vykreslit vlastní controlbox? Velikosti tlačítek? Barvy pro stavy tlačítek (normal, hot, pressed)? Červená barva pro close button? Aktuálně použitý font a jeho size pro symboly v tlačítkách dle nastavení ve windows 7 či windows 10 ? Jak tento styl vnutit toolstripu, aby vypadal stejně jako tlačítka v záhlaví ?

Dost šílená práce, aby vzhled záhlaví vypadal podobně jako současné aplikace např. office, vložit do záhlaví vlastní QAT (Quick Access Toolbar) s dalším panelem tlačítek pod záhlavím , že?

Snad už ani nechci vytvářet vlastní barvy, postačí mi do zvětšené neklientské oblasti záhlaví vložit toolstrip, který převezme aktuální styl. Pokud to nelze nastavit, tak cestou vlastního rendereru ?

Děkuji za případnou reakci.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zkoušel jsem něco najít ohledně tlačítek (control box, location, size) ...

WM_GETTITLEBARINFOEX message ? Jak získat ve VB.Net structuru TITLEBARINFOEX?

https://msdn.microsoft.com/en-us/library...

Vypadá, že se lze dostat k RECT záhlaví i jednotlivých tlačítek...

TITLEBARINFOEX structure

https://msdn.microsoft.com/en-us/library...

...

How to retrieve the size of the Minimize, Maximize and Close button of a Window?

https://html.devhelping.com/article/1988...

...

Nevede to k ničemu. Jak se dobrat spolehlivých výsledků?

Používá se k tomu WPF? Šablona formuláře vytvořená ve WPF pro VB.NET ?

...

http://web.archive.org/web/2008122416144...://shellrevealed.com/blogs/shellblog/archive/2006/10/12/Frequently-asked-questions-about-the-Aero-Basic-window-frame.aspx

...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Přidávám ukázku získat location a size controlboxu :

<StructLayout(LayoutKind.Sequential)>
    Public Structure RECT
        Public left As Integer
        Public top As Integer
        Public right As Integer
        Public bottom As Integer
    End Structure

    Enum DWMWINDOWATTRIBUTE As Integer
        NCRenderingEnabled = 1
        NCRenderingPolicy
        TransitionsForceDisabled
        AllowNCPaint
        CaptionButtonBounds
        NonClientRtlLayout
        ForceIconicRepresentation
        Flip3DPolicy
        ExtendedFrameBounds
        HasIconicBitmap
        DisallowPeek
        ExcludedFromPeek
        Cloak
        Cloaked
        FreezeRepresentation
    End Enum

    <DllImport("dwmapi.dll")>
    Public Shared Function DwmGetWindowAttribute(ByVal hwnd As IntPtr, ByVal dwAttribute As Integer, <Out()> ByRef pvAttribute As RECT, ByVal cbAttribute As Integer) As Integer
    End Function

Public Shared Function GetControlBoxRectangle(ByVal handle As IntPtr) As Rectangle
        Dim r As Rectangle = Rectangle.Empty
        Dim rc As RECT = New RECT()
        If Not Environment.OSVersion.Version.Major < 6 Then
            Dim res As Integer = DwmGetWindowAttribute(handle, DWMWINDOWATTRIBUTE.CaptionButtonBounds, rc, Marshal.SizeOf(GetType(RECT)))
            r = Rectangle.FromLTRB(rc.left, rc.top, rc.right, rc.bottom)
        End If
        Return r
    End Function

Ve Win7 šířka souhlasí, výška je větší než skutečnost, ve Win10 je to obráceně, výška souhlasí, ale šířka je o pár pixelů větší z levé strany. Win8 a Vista nenám možnost zkusit. Pro WinXp nelze použít.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nevypadá, že to bude někomu k užitku...

Získání rectangle jednotlivých tlačítek controlboxu titlebaru pomocí TITLEBARINFOEX structure :

    Friend Const WM_GETTITLEBARINFOEX As Integer = &H33F
    Friend Const CCHILDREN_TITLEBAR As Integer = 5

    <StructLayout(LayoutKind.Sequential)>
    Friend Structure TITLEBARINFOEX
        Public cbSize As Integer
        Public rcTitleBar As RECT  
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=CCHILDREN_TITLEBAR + 1)>
        Public rgstate As Integer()
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=CCHILDREN_TITLEBAR + 1)>
        Public rgrect As RECT()  
    End Structure

    <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    Friend Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal uMsg As Integer, ByVal wParam As IntPtr, ByRef lParam As TITLEBARINFOEX) As IntPtr
    End Function

    Friend Shared Function GetTitleBarInfoEx(ByVal hWnd As IntPtr) As TITLEBARINFOEX
        Dim tbi As TITLEBARINFOEX = New TITLEBARINFOEX()
        tbi.cbSize = Marshal.SizeOf(GetType(TITLEBARINFOEX))
        SendMessage(hWnd, WM_GETTITLEBARINFOEX, IntPtr.Zero, tbi)
        Return tbi
    End Function

Zprvu se mi nedařilo správně sestavit structuru TITLEBARINFOEX, ale vypadá, že takhle to funguje.

Netuším, proč se mi nevrací RECT rcTitleBar správně, ale kupodivu RECT pro jednotlivá tlačítka odpovídá ve Win10 přesně skutečnosti, rgRect(2) pro minimize button, rgRect(3) pro maximize button, rgRect(5) pro close button.

Detaily struktury TITLEBARINFOEX :

https://msdn.microsoft.com/en-us/library...

Máte-li rozšířeno kreslení do neklientské oblasti, pak obrazná kontrola získaného rectangle close buttonu pomocí modrého orámování v události Paint :

Private Sub Form1_Paint(ByVal sender As Object, _
      ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

        Dim tbiex As TITLEBARINFOEX = GetTitleBarInfoEx(Me.Handle)
        With tbiex.rgrect(5)
            Dim r As Rectangle = Rectangle.FromLTRB(.left, .top, .right, .bottom)
            Dim rtc As Rectangle = Me.RectangleToClient(r)
            e.Graphics.DrawRectangle(Pens.Blue, rtc)
        End With
End Sub

...

Painting Vista's Aero NonClientArea in VB.NET :

https://www.codeproject.com/Articles/442...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den. Tady vám posílám tip na vlastní vzhled okna.

Vytvořte si nové okno

FormBorderStyle=None

Vložte panel1 jako záhlaví s parametrem Dock=Top. Šířku a výšku si zadejte vlastní

Vložte panel2 jako levý okraj s parametrem Dock=Lef. Šířku dejte 2 nebo 3 a výšku podle výšky okna. To samé pro pravý okraj (Dock=Right) a spodní okraj (Dock=Buttom).

Barvy si zvolte podle svého vkusu.

Na záhlaví si vložte dva PictureBox s obrázky pro minimalizaci a uzavření. Oba dva obrázky musíte propojit v programu, aby plnily funkci lišty nebo ukončení.

Vložte tento kód, aby jste mohl oknem pohybovat.


#Region "Pohybování oknem"

  ' Pohybování oknem myší
  Private Sub tbDatCas_MouseDown(sender As Object, e As MouseEventArgs) Handles tbDatCas.MouseDown, Me.MouseDown, Panel6.MouseDown, pbPicture.MouseDown
                                                                                
    xP = Control.MousePosition.X - Me.Location.X
    yP = Control.MousePosition.Y - Me.Location.Y
  End Sub

  Private Sub Panel1_MouseMove(sender As Object, e As MouseEventArgs) Handles tbDatCas.MouseMove, Me.MouseMove, Panel6.MouseMove, pbPicture.MouseMove
                                                                              
    If e.Button = Windows.Forms.MouseButtons.Left Then
      newPoint = Control.MousePosition
      newPoint.X -= (xP)
      newPoint.Y -= (yP)
      Me.Location = newPoint
    End If
  End Sub

#End Region

Když si do záhlaví dáte něco, co vám zakryje Panel1, musíte to napsat za Handles do první i druhé procedury. Jednou s MouseDown a po druhé s MouseMove

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji za vaši reakci a také za tip, form s nastavením FormBorderStyle=None a vykreslení vlastního záhlaví je nejspíš nejlepší varianta. Akorát by bylo pěkné vykreslit tlačítka, aby vzhledem zapadla dle operačního systému a aktuálních nastavení.

Při ponechání záhlaví včetně controlboxu se po změně a vykreslení vlastní barvy záhlaví dostanou tlačítka controlboxu (min. ,max. či restore a close) do pozadí, navíc netuším jak změnit barvy pro stavy tlačítek, je-li aktivní či ne , stisknuté či nepřístupné. K tomu by bylo nutné se dostat k jejich handle a události Paint, lze-li ?

K vykreslení vlastních tlačítek v záhlaví jsem zkoušel VisualStyleRenderer a pomocí metody PaintBackground lze vykreslit různé prvky s nastavením zobrazeného stavu, bohužel nastavit vlastní barvu se mi nepodařilo a vzhled a velikost nakonec stejně neodpovídá vzhledu, který se změní, když se do překreslení formuláře vloží DWM. Posouvání a změna velikosti borderless formuláře, lze také řešit ve WndProc.

Pro vytvoření vlastního panelu a náhradního controlboxu používáte toolstrip? Vlastní kreslení? Vložené buttony či pictureboxy s ikonami v panelu?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ty jednodušší tlačítka jsem si dělal sám pomocí PhotoFiltre X, jako PNG soubory o velikosti 128 x 128. S tím, jestli je tlačítko stisknuté nebo ne, s tím si vrásky nedělám. Na internetu se dá sehnat spousta tlačítek, jak ICO, tak PNG. Nemusíte se vehementně držet toho, jak se to dělá. Vložte trochu fantazie a uvidíte, že vás výsledek potěší. Navíc si do PopUp menu můžete dát změnu barev záhlaví a orámování. Držím palce.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Děkuji za další reakci a podporu. Sbírám inspiraci pro oživení fantazie,tak moc díky.

Co na obrázky tlačítek použít nějaký font se symboly a vykreslit vybrané symboly za běhu?

Zkoušel někdo? Doporučení na druh fontu? Načtení fontu dle OS? Stejná šířka symbolů? Jiná úskalí?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den. Nemusíte používat jako tlačítka obrázky, to byl jen takový můj nápad. Použijte Button a vložte do něj jakýkoli text nebo obrázek. Dá se nastavit i to, že po najetí kurzoru se změní barva. Je tam toho spousta a je jen na vás, co použijete. Potřebujete-li písmo se stejným odsazením, použijte třeba Consolas. Používá se v kalkulačkách, protože škrtá nuly nebo v kondiciogramech. Potřebujete-li rychle nějaké znaky nebo šipky, tak můžete použít písmo Wingdings 1 až 3. Zkuste ve Wordu písma, která by se dala ještě použít, je jich tam hafo. Já jsem si šipky vyrobil ve Photo Filtre X. Je to celkem dobrý program a hlavně pracuje s vrstvami a to je při vytváření tlačítek důležité. Zkoušet, zkoušet, zkoušet.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback