DwmExtendFrameIntoClientArea without Aero Glass

前端 未结 3 1308
遥遥无期
遥遥无期 2021-02-05 22:20

Using the DwmExtendFrameIntoClientArea API call with Aero Glass enabled works just fine. However, I want it to work when Aero Glass is disabled as well, like how it

3条回答
  •  猫巷女王i
    2021-02-05 22:40

    Nir's answer is correct; when composition is disabled you have to draw that area yourself.

    i can show you the code i have in the paint handler of the panel at the top of my form - the panel normally responsible for drawing the 0x00000000 transparent black to make the glass appear:

    Psuedo-code:

    procedure DrawGlassHeaderArea(g: Graphics; r: Rectangle; IsFormFocused: Boolean);
    const
       clFakeGlassColor = $00EAD1B9;  //(185, 209, 234) This is the fake foreground glass color (for use when composition is disabled)
       clFakeGlassColorUnfocused = $00F2E4D7; //(215, 228, 242) This is the fake background glass color (for use when composition is disabled)
    begin
       if Dwm.IsCompositionEnabled then
       begin
          g.FillRectangle(r, 0x00000000); //fill rectangle with transparent black
       end
       else
          //Composition disabled; fake it like Microsoft does
    
          //The color to use depends if the form has focused or not
          Color glassColor;
          if (IsFormFocused) then
             c = clFakeGlassColor 
          else
             c = clFakeGlassColorUnfocused;
    
          g.FillRectangle(r, glassColor); //fill rectangle with fake color
    
    
          //Now we have to draw the two accent lines along the bottom
          Color edgeHighlight = ColorBlend(Colors.White, glassColor, 0.33); //mix 33% of glass color to white
          Color edgeShadow = ColorBlend(Colors.Black, glassColor, 0.33); //mix 33% of glass color to black
    
          //Draw highlight as 2nd-last row:
          g.DrawLine(edgeHighlight, Point(r.Left, r.Bottom-2), Point(r.Right, r.Bottom-2);
    
          //Draw shadow on the very last row:
          g.DrawLine(edgeHighlight, Point(r.Left, r.Bottom-1), Point(r.Right, r.Bottom-1);
       end;
    end;
    

    Sample usage

    procedure MyForm.PaintBox1Paint(PaintEventArgs e)
    begin
       DrawGlassHeaderArea(e.Graphics, PaintBox1.ClientRectangle, this.HasFocus); 
    end;
    

    Bonus Screenshot

    enter image description here

    Update 7/9/2014

    @JakePetroules was right, and i was wrong. The "blue" used for fake glass is not hard-coded into Windows. And it is accessible using GetThemeColor.

    I coded up all the available colors (TMT_COLOR) available for a Window class:

    enter image description here

    Note: For more information about Classes, Parts, and States, see Aero Style Classes, Parts, and States

    When using:

    • Class: Window
    • Part: WP_CAPTION
    • State: n/a (StateID is not used for the Caption part, nor the entire Window class)

    and fetch the color code propertyID:

    • TMT_FILLCOLORHINT: for when the window has focus
    • TMT_BORDERCOLORHINT: for when the window does not have focus

    you get the two important colors:

    enter image description here

    The pseudo-code i now use to get the fake glass color:

    public Color GetFakeClassColor(Boolean isWindowFocused=true)
    {
       static Color fakeGlass= 0x00B8D0E9; //the correct answer anyway
    
       if ((GetThemeAppProperties() && STAP_ALLOW_CONTROLS) == 0)
          return fakeGlass;
    
       hTheme = OpenThemeData(GetDesktopWindow(), "Window");
       if (hTheme = 0)
          return fakeGlass;
    
       Int32 propID;
       if (isWindowFocused)
           propID= TMT_FILLCOLORHINT; //The color used as a fill color hint for custom controls.
       else
           propID= TMT_BORDERCOLORHINT; //The color used as a border color hint for custom controls.
    
       DWORD rgb;
       if (Failed(GetThemeColor(hTheme, WP_CAPTION, 0, propID, ref rgb))
          return fakeGlass;
    
       Result = new Color(rgb);
    }
    

    In reality, since i use Delphi, my actual code is:

    function GetFakeGlassColor(IsWindowFocused: Boolean=True): TColor;
    var
        ted: TThemedElement;
        hTheme: THandle;
        propID: Integer;
        rgb: DWORD;
    begin
        Result := $00B8D0E9; //the correct answer anyway
    
        //We can't use the ThemeServcies.ThemesEnabled, as that mistakenly checks for version 6 of the common controls library
        //Themes can be enabled without using ComCtl V6, or common controls at all
        if not ThemeServices.ThemesAvailable then
            Exit;
        if (GetThemeAppProperties and STAP_ALLOW_CONTROLS) = 0 then
            Exit;
    
        htheme := ThemeServices.Theme[teWindow];
        if hTheme = 0 then
            Exit;
    
        if IsWindowFocused then
            propID := TMT_FILLCOLORHINT //The color used as a fill color hint for custom controls.
        else
            propID := TMT_BORDERCOLORHINT; //The color used as a border color hint for custom controls.
    
        if Failed(GetThemeColor(hTheme, WP_CAPTION, 0, propID, {var}rgb)) then
            Exit;
    
        Result := rgb;
    end;
    

提交回复
热议问题