ツールバーの背景をVistaや7のExplorerみたいにしたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

ツールバーの背景をVistaや7のExplorerみたいにしたい

#1

投稿記事 by tk-xleader » 3年前

C++でWindows APIを直接叩いてます。実行環境はWindows10 64bitです。
Windows APIで作成したツールバーの背景をVistaや7のExplorerのツールバー(画像参照)みたいにしたいのですが、現在はとりあえず以下のような、ツールバーのプロシージャを乗っ取ってWM_ERASEBKGNDを捕まえてそこで自力で背景を作成するという、工夫もへったくれもない書き方をしています。

コード:

#include<Windows.h>
#include<tchar.h>
#include<CommCtrl.h>

WNDPROC lpfnDefToolbarProc;
LRESULT CALLBACK ToolbarProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
	switch (uMsg){
	case WM_ERASEBKGND:
		RECT clientrc;
		GetClientRect(hWnd, &clientrc);
		HDC hdc = (HDC)wParam;
		// ちょっとずつ色を変えながら線を引いていく。
		for (int i = 0; i < clientrc.bottom / 2; i++){
			COLORREF color = RGB(255 - i*10, 255 - i*2, 255 - i*3);
			HPEN hPen = CreatePen(PS_SOLID, 1, color);
			HPEN hPrevPen = (HPEN)SelectObject(hdc, hPen);
			MoveToEx(hdc, 0, i, nullptr);
			LineTo(hdc, clientrc.right, i);
			SelectObject(hdc, hPrevPen);
			DeleteObject(hPen);
		}
		//立体感を出すために下半分の色調は変える。
		for (int i = clientrc.bottom / 2; i < clientrc.bottom; i++){
			COLORREF color = RGB(i,128+i*3,96+i*6);
			HPEN hPen = CreatePen(PS_SOLID, 1, color);
			HPEN hPrevPen = (HPEN)SelectObject(hdc, hPen);
			MoveToEx(hdc, 0, i, nullptr);
			LineTo(hdc, clientrc.right, i);
			SelectObject(hdc, hPrevPen);
			DeleteObject(hPen);
		}
		return TRUE;
	}
	return CallWindowProc(lpfnDefToolbarProc, hWnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK MainProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
	static HWND hToolbar;
	switch (uMsg){
	case WM_CREATE:
		InitCommonControls();
		hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, nullptr, WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT, 0, 0, 10, 20, hWnd, nullptr, nullptr, nullptr);
		lpfnDefToolbarProc = (WNDPROC)SetWindowLongPtr(hToolbar, GWLP_WNDPROC, (LONG_PTR)&ToolbarProc);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_SIZE:
		SIZE size = { LOWORD(lParam), HIWORD(lParam) };
		MoveWindow(hToolbar, 0, 0, size.cx, 30, TRUE);
		return 0;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow){
	WNDCLASSEX wndClass = {};
	wndClass.cbSize = sizeof(wndClass);
	wndClass.style = CS_VREDRAW | CS_HREDRAW;
	wndClass.lpfnWndProc = &MainProc;
	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndClass.hIcon = wndClass.hIconSm = LoadIcon(nullptr, (LPCTSTR)IDI_APPLICATION);
	wndClass.hCursor = LoadCursor(nullptr, (LPCTSTR)IDC_ARROW);
	wndClass.lpszClassName = _T("SampleWindow");
	LPCTSTR lpClassAtom = (LPCTSTR)RegisterClassEx(&wndClass);
	if (!lpClassAtom)return -1;

	HWND hWnd = CreateWindow(lpClassAtom, _T("Toolbar Sample"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		nullptr, nullptr, nullptr, nullptr);
	if (!hWnd) return -1;

	ShowWindow(hWnd, SW_SHOWDEFAULT);
	UpdateWindow(hWnd);

	MSG msg;
	while (int retGM = GetMessage(&msg, nullptr, 0, 0)){
		if (retGM == -1)return -1;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}
ですが、Explorerで利用されているくらいなので、背景を自力で描画する他にSDKで何かこれを実現する方法があるのではないかと思うのですが、ググってもほとんど情報が見つからないです。やはり自力で頑張る以外の方法はないのでしょうか?
添付ファイル
toolbar_vista.png
Windows VistaのExplorerのスクリーンショット(Wikipediaから)。

Math

Re: ツールバーの背景をVistaや7のExplorerみたいにしたい

#2

投稿記事 by Math » 3年前

基本的にWindows APIでは無理だと思います。DirectXが必要でDxLibなどを使う必要があります。
VistaからOSに.NetFrameWorkが採用され”WPF"をベースとした立体的でカラフルなWindowsになりました。”WPF"アプリはVS2008のVB,C#で可能です。”WPF"はDirectX,.NetFrameWorkベースで普通は”xaml"で記述します。
(DirectXはMicrosoftさんのゲーム技術からOSに昇格したのでDirectX10以降はMicrosoftのガードがきつくなったような気がします)
http://csi.nisinippon.com/wpf2.png

(WPFはゲームには向いてないとMicrosoftさんも認めていて”DxLib"の方が圧倒的に有利です。)

Math

Re: ツールバーの背景をVistaや7のExplorerみたいにしたい

#3

投稿記事 by Math » 3年前

[WPF]vb-program ---[vb2008コマンドプロンプトを使う。Wクリックで動く]
普通にボタンを表示するだけで”グラデーション”が付く。http://csi.nisinippon.com/wpf3.png
p3.bat

コード:

C:\Windows\Microsoft.NET\Framework64\v3.5\vbc.exe ^
/reference:PresentationCore.dll ^
/reference:PresentationFramework.dll ^
/reference:WindowsBase.dll ^
/target:winexe ^
/out:p3.exe ^
/optimize+ ^
p3.vb
p3.exe
pause
p3.vb

コード:

Imports System.Windows
Imports System.Windows.Controls
Module Module1
    <STAThread()> _
    Sub Main()
	Dim app As Application = New Application()
        app.Run(new Window1())
    End Sub
End Module
Public Class Window1
                   Inherits Window

    Private btn As Button
 
    Public Sub New()
      btn = New Button()
      btn.Content = "btn"

      Me.AddChild(Me.btn)
      Me.Width = 250
      Me.Height = 70

      AddHandler btn.Click, AddressOf btn_Click
    End Sub
    Private Sub btn_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
		Me.Title = "Hello World!"
    End Sub
  End Class
実行結果

コード:

D:\z\_ps\001\2016_0719_w10_C_prog\prog\b1\bwpf>C:\Windows\Microsoft.NET\Framework64\v3.5\vbc.exe /reference:PresentationCore.dll /reference:PresentationFramework.dll /reference:WindowsBase.dll /target:winexe /out:p3.exe /optimize+ p3.vb
Microsoft (R) Visual Basic Compiler Version 9.0.30729.8763
Copyright (C) Microsoft Corporation. All rights reserved.


D:\z\_ps\001\2016_0719_w10_C_prog\prog\b1\bwpf>p3.exe

Math

Re: ツールバーの背景をVistaや7のExplorerみたいにしたい

#4

投稿記事 by Math » 3年前

[WPF]C#-program Windows の機能のみ使用。PowerSell_iseでUnixコマンドのcsc.exeコンパイラのエイリアスcscをつかう。
http://csi.nisinippon.com/wpfcs.png
スクリプト

コード:

csc /r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll" `
/r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\PresentationCore.dll" `
/r:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\PresentationFramework.dll" `
.\cwpf1.cs 

ls
.\cwpf1.exe
C# code[cwpf1.cs]

コード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CS_wpf_App
{
    public class program
    {
        [STAThread]
        static void Main(string[] args)
        {
            var app = new Application();
            app.Run(new Window1 { Title = "csc samp", Width = 480, Height = 150, });
        }
    }

    public  class Window1 : Window
    {
	Grid grid1;
        Label firstNameLabel;
        Label lastNameLabel;
        TextBox firstName;
        TextBox lastName;
        Button submit;
        Button clear;

        public Window1()
        {
            this.grid1 = new Grid();

            grid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(100) }); 
            grid1.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) }); 
            grid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); 
            grid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); 
            grid1.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); 
            
            firstNameLabel = new Label();
            firstNameLabel.Content = "姓:";
            grid1.Children.Add(firstNameLabel);

            firstName = new TextBox();
            firstName.Margin = new Thickness(0, 5, 10, 5);
            Grid.SetColumn(firstName, 1);
            grid1.Children.Add(firstName);

            lastNameLabel = new Label();
            lastNameLabel.Content = "名:";
            Grid.SetRow(lastNameLabel, 1);
            grid1.Children.Add(lastNameLabel);

            lastName = new TextBox();
            lastName.Margin = new Thickness(0, 5, 10, 5);
            Grid.SetColumn(lastName, 1);
            Grid.SetRow(lastName, 1);
            grid1.Children.Add(lastName);

            submit = new Button();
            submit.Content = "メッセージ";
            Grid.SetRow(submit, 2);

            LinearGradientBrush buttonBrush = new LinearGradientBrush();
            buttonBrush.StartPoint = new Point(0, 0.5);
            buttonBrush.EndPoint = new Point(1, 0.5);
            buttonBrush.GradientStops.Add(new GradientStop(Colors.Green, 0));
            buttonBrush.GradientStops.Add(new GradientStop(Colors.White, 0.9));
            
            submit.Background = buttonBrush;
            submit.FontSize = 14;
            submit.FontWeight = FontWeights.Bold;

            grid1.Children.Add(submit);

            clear = new Button();
            clear.Content = "クリア";
            Grid.SetRow(clear, 2);
            Grid.SetColumn(clear, 1);

            LinearGradientBrush buttonBrush2 = new LinearGradientBrush();
            buttonBrush2.StartPoint = new Point(0, 0.5);
            buttonBrush2.EndPoint = new Point(1, 0.5);
            buttonBrush2.GradientStops.Add(new GradientStop(Colors.Blue, 0));
            buttonBrush2.GradientStops.Add(new GradientStop(Colors.White, 0.9));
            
            clear.Background = buttonBrush2;
            clear.FontSize = 14;
            clear.FontWeight = FontWeights.Bold;
            grid1.Children.Add(clear);

	    this.AddChild(grid1);

            submit.Click += new RoutedEventHandler(submit_Click);

            clear.Click += new RoutedEventHandler(clear_Click);

            this.Loaded += new RoutedEventHandler(Window1_Loaded); 

        }

        private void Window1_Loaded(object sender, RoutedEventArgs e)
        { 
    		firstName.Text = "Window1_Loaded !";
        } 
 
        void submit_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text);
        }
        
        void clear_Click(object sender, RoutedEventArgs e)
        {
            firstName.Text = "";
            lastName.Text = "";
        }
    }
}

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: ツールバーの背景をVistaや7のExplorerみたいにしたい

#5

投稿記事 by tk-xleader » 3年前

回答ありがとうございます。やはりAPI直叩きで実現しようと思ったら背景を自力で描画する他ないですか…

ただ、グラデーションとアルファブレンドについては、それぞれGradiantFill、AlphaBlend関数があることが分かったので、これを使って自力で描画するという方針で押し切ろうと思います。

閉鎖

“C言語何でも質問掲示板” へ戻る