LoginSignup
13
9

More than 5 years have passed since last update.

Siv3D でおしゃれなアプリランチャーを作ろう (49 行)

Last updated at Posted at 2015-12-03

0.gif

1 台のパソコンで複数の作品を展示するときに、ショートカットをデスクトップに雑然と並べるだけではプレイヤーに不親切です。Siv3D March 2016 を使って、おしゃれなアプリランチャーを作りましょう。このアプリランチャーは、Siv3D 製以外のアプリや、Web ブラウザを使った作品の起動にも対応します。

1. 外部アプリを起動しよう

System::CreateProcess() は、第 1 引数で指定した外部のプログラムを実行します。

サンプル 1-1

# include <Siv3D.hpp>

void Main()
{
    System::CreateProcess(L"C:/Windows/System32/notepad.exe");

    while (System::Update())
    {

    }
}

戻り値の ProcessInfo を通して、プロセスが実行中であるかを調べられます。
外部アプリケーションが実行されている間はランチャーを最小化するようにしましょう。

サンプル 1-2

# include <Siv3D.hpp>

void Main()
{
    Optional<ProcessInfo> process = System::CreateProcess(L"C:/Windows/System32/notepad.exe");

    while (System::Update())
    {
        if (process)
        {
            if (process->isRunning())
            {
                Window::Minimize();
            }
            else
            {
                Window::Restore();
                process = none;
            }
        }
    }
}

2. Web ブラウザを起動しよう

System::CreateProcess() の第 2 引数には、外部のプログラムを起動する際のコマンドラインオプションを指定できます。Internet Explorer の場合は、-new [URL] で、指定した URL をオープンします。

サンプル 2-1

# include <Siv3D.hpp>

void Main()
{
    Optional<ProcessInfo> process = System::CreateProcess(L"C:/Program Files/Internet Explorer/iexplore.exe",
        L"-new http://play-siv3d.hateblo.jp/");

    while (System::Update())
    {
        if (process)
        {
            if (process->isRunning())
            {
                Window::Minimize();
            }
            else
            {
                Window::Restore();
                process = none;
            }
        }
    }
}

3. 選択画面を作ろう

アプリの名前、アプリのパス、コマンドラインオプションを配列に用意しましょう。

サンプル 3-1

3-1.png

# include <Siv3D.hpp>

struct Application
{
    String name;
    FilePath path;
    String option;
};

void Main()
{
    Window::Resize(640, 310);
    Window::SetStyle(WindowStyle::NonFrame);
    const Font font(20, Typeface::Light);

    const Array<Application> applications =
    {
        { L"メモ帳", L"C:/Windows/System32/notepad.exe", L"" },
        { L"ペイント", L"C:/Windows/System32/mspaint.exe", L"" },
        { L"電卓", L"C:/Windows/System32/calc.exe", L"" },
    };

    Optional<ProcessInfo> process;

    while (System::Update())
    {
        for (auto i : step(applications.size()))
        {
            const Rect rect(40, 40 + i * 80, 250, 60);

            rect.draw();

            font(applications[i].name).draw(rect.pos.movedBy(24, 8), Palette::Black);

            if (rect.leftClicked)
            {
                process = System::CreateProcess(applications[i].path, applications[i].option);
            }
        }

        if (process)
        {
            if (process->isRunning())
            {
                Window::Minimize();
            }
            else
            {
                Window::Restore();
                process = none;
            }
        }
    }
}

4. アプリの説明とサムネイル画像を表示しよう

アプリの説明とサムネイル画像を加えます。

サンプル 4-1

4-1.png

# include <Siv3D.hpp>

struct Application
{
    String name;
    FilePath path;
    String option;
    String description;
    Texture thumbnail;
};

void Main()
{
    Window::Resize(640, 310);
    Window::SetStyle(WindowStyle::NonFrame);
    const Font font(20, Typeface::Light), fontDesc(16);
    const Texture texture(Image(L"Example/Windmill.png").scale(270, 180));

    const Array<Application> applications =
    {
        { L"メモ帳", L"C:/Windows/System32/notepad.exe", L"", L"メモを書けるよ", texture },
        { L"ペイント", L"C:/Windows/System32/mspaint.exe", L"", L"絵を描けるよ", texture },
        { L"電卓", L"C:/Windows/System32/calc.exe", L"", L"計算してくれるよ", texture },
    };

    Optional<ProcessInfo> process;
    size_t currentIndex = 0;

    while (System::Update())
    {
        for (auto i : step(applications.size()))
        {
            const Rect rect(40, 40 + i * 80, 250, 60);

            if (rect.mouseOver)
            {
                currentIndex = i;
            }

            rect.draw();

            font(applications[i].name).draw(rect.pos.movedBy(24, 8), Palette::Black);

            if (rect.leftClicked)
            {
                process = System::CreateProcess(applications[i].path, applications[i].option);
            }
        }

        applications[currentIndex].thumbnail.draw(330, 40);

        fontDesc(applications[currentIndex].description).drawCenter({ 465, 248 }, Palette::White);

        if (process)
        {
            if (process->isRunning())
            {
                Window::Minimize();
            }
            else
            {
                Window::Restore();
                process = none;
            }
        }
    }
}

5. 完成

デザインをアレンジしましょう。今回は付箋や写真をイメージしました。
参考: Play Siv3D! サンプル | 付箋

サンプル 5-1 (49 行)

5-1.png

# include <Siv3D.hpp>

struct Application
{
    String name;
    FilePath path;
    String option;
    String description;
    Texture thumbnail;
};

void Main()
{
    Window::Resize(640, 310);
    Window::SetStyle(WindowStyle::NonFrame);
    Graphics::SetBackground(Color(240, 250, 230));
    const Font font(20, Typeface::Light), fontDesc(16);
    const Texture texture(Image(L"Example/Windmill.png").scale(270, 180));

    const Array<Application> applications =
    {
        { L"メモ帳", L"C:/Windows/System32/notepad.exe", L"", L"メモを書けるよ", texture },
        { L"ペイント", L"C:/Windows/System32/mspaint.exe", L"", L"絵を描けるよ", texture },
        { L"電卓", L"C:/Windows/System32/calc.exe", L"", L"計算してくれるよ", texture },
    };

    Array<double> angleOffsets(applications.size());

    for (auto& angleOffset : angleOffsets)
    {
        angleOffset = Random(-1.5, 1.5);
    }

    Optional<ProcessInfo> process;
    size_t currentIndex = 0;

    while (System::Update())
    {
        for (auto i : step(applications.size()))
        {
            const Rect rect(40 + i % 2 * 20, 40 + i * 80, 250, 60);

            if (rect.mouseOver)
            {
                currentIndex = i;
            }

            const bool selected = (currentIndex == i);

            Graphics2D::SetTransform(Mat3x2::Rotate(Radians(selected ? 3 : 1), rect.pos));
            rect.drawShadow({ 1, 1 }, 12, -1, ColorF(0, 0.4));
            Graphics2D::SetTransform(Mat3x2::Identity());

            rect.draw(HSV(i * 40, 0.6, selected ? 1.0 : 0.95));
            font(applications[i].name).draw(rect.pos.movedBy(24, 8), Palette::Black);

            if (rect.leftClicked)
            {
                process = System::CreateProcess(applications[i].path, applications[i].option);
            }
        }

        const Vec2 pinPos(465, 50);

        Graphics2D::SetTransform(Mat3x2::Rotate(Radians(angleOffsets[currentIndex]), pinPos));
        Rect(330, 40, texture.size).drawShadow({ 2, 2 }, 12, 3, ColorF(0, 0.4));
        applications[currentIndex].thumbnail.draw(330, 40).drawFrame(10, 0).stretched(-10).drawFrame(1, 0, Palette::Gray);
        Graphics2D::SetTransform(Mat3x2::Identity());

        Circle(pinPos, 6).drawShadow({ 3, 3 }, 4, 1);
        Circle(pinPos, 6).draw(HSV(0, 0.7, 0.9)).stretched(-2).draw(HSV(0, 0.9, 0.9));
        fontDesc(applications[currentIndex].description).drawCenter({ pinPos.x, 248 }, Palette::Black);

        if (process)
        {
            if (process->isRunning())
            {
                Window::Minimize();
            }
            else
            {
                Window::Restore();
                process = none;
            }
        }
    }
}

このページの最初のムービーに出てくるサムネイルを使いたい場合は、以下の 3 つの画像をダウンロードしてください。

0.png 1.png 2.png

明日の記事は @Sigureya さんです。
よろしくお願いします。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9