[C++] 229 Visual C++ : StoreAppLicense内データを取得

[Windows11, Visual C++2017, FLTK 1.3.8, NO IDE]

ストアアプリ起動時にアドオンライセンスの取得状況をチェックする仕組みを作りました。

StoreAppLicenseデータをJSON型で入手し、これを解析してアドオンライセンスのbool値を取得します。

json11というライブラリを使って解析しました。

#include "json11.hpp"
#include <winrt/Windows.Services.Store.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>

using namespace winrt;
using namespace winrt::Windows::Services::Store;
using namespace winrt::Windows::Foundation::Collections;

bool AddOn1_bool;
bool AddOn2_bool;

int main(int argc, char** argv) {
	// StoreContext取得
	StoreContext _storeContext = StoreContext::GetDefault();

	// StoreAppLicenseを非同期にて取得
	winrt::Windows::Foundation::IAsyncOperation<StoreAppLicense> _storeAppLicense = _storeContext.GetAppLicenseAsync();
	StoreAppLicense _storeAppLicense2 = _storeAppLicense.get();

	// StoreAppLicenseデータをJSON型で取得
	hstring data = _storeAppLicense2.ExtendedJsonData();
	string data_str = winrt::to_string(data);

	// JSONデータを解析
	string err, err1, err2;
    auto data_json = json11::Json::parse(data_str, err);

	// アドオン名とライセンスbool値を取得
	int num_addon = 1;
	for (auto &k : data_json["productAddOns"].array_items()) {
        cout << num_addon << ": " <<  k.dump() << endl;

		switch (num_addon){
			case 1:{
				auto data_json1 = json11::Json::parse(k.dump(), err1);
				string AddOnName1 = data_json1["inAppOfferToken"].string_value();
				AddOn1_bool = data_json1["isActive"].bool_value();
				cout << AddOnName1 << " : " << AddOn1_bool << endl;
				break;
			}
			case 2:{
				auto data_json2 = json11::Json::parse(k.dump(), err2);
				string AddOnName2 = data_json2["inAppOfferToken"].string_value();
				AddOn2_bool = data_json2["isActive"].bool_value();
				cout << AddOnName2 << " : " << AddOn2_bool << endl;
				break;
			}
		}
		num_addon++;
	}
	<以下略>
}

[C++] 228 Visual C++ : Makefile NMAKE版

[Windows11, Visual C++2017, FLTK 1.3.8, NMAKE 14.30, NO IDE]

カラーアプリのMakefileをGNU Make版からMicrosoft NMAKE版に書き換えました。

まずMakefileの文字コードをUTF-8からShift-JISに変更しました。変更しておかないと” U1033 fatal error : ‘:’ unexpected”という意味不明なエラーに悩まされます。

NMAKEではaddprefixやpatsubstのようなこじゃれた関数は用意されていなかったので元のもっさりした書き方に戻しました。あと全依存ファイルを意味する自動変数$^を$**に書き換えました。

修正はこの3点のみでした。これなら普段はGNU Makeで開発し、公開するときだけNMAKEを使っても良さそうです。

StackOverflow英語版ではNMAKEは低機能で使い物にならないなど散々な書かれようですが、ライセンス抵触回避のために存在してくれるだけありがたいです。

なおMacOSで製作したアプリをソースコード公開なしで頒布したい場合は修正BSDライセンスのCMakeでビルドするのが適切かと思われます。

今回のWindowsのケースでもCMakeを使うという選択肢はありましたが、手間を考えてNMAKEにしました。実際初めてでも1時間足らずで移行できました。コツを掴んだので次回からはものの数分でしょう。

# NMAKE版
# コンパイラ設定他
COMPILER = cl
DEBUG = /D "_DEBUG"
CONSOLE = /SUBSYSTEM:CONSOLE
WINDOWS = /SUBSYSTEM:WINDOWS
LINKER = LINK
RESOURCE = "ColorSampleJP.res"

# オプション設定
CPPFLAGS = /std:c++17 /GS /W3 /Zc:wchar_t /ZI /Gm- /Od /sdl  /Zc:inline /fp:precise /D "_UNICODE" \
/errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /FC /c /diagnostics:column /EHsc
LDFLAGS = /DEBUG /MACHINE:X64 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /OPT:REF /INCREMENTAL:NO

# includeパス(-I)
INCLUDE = /I"C:\packages\fltk-1.3.8\include" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\atlmfc\include" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\cppwinrt" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\ucrt" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\shared" \
/I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Include\um" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt"

INCLUDE2 = /I"D:\code\VC++\Projects\ColorSampleJP\include" \
/I"D:\code\VC++\Projects\ColorConvert\ColorConvert" \
/I"D:\code\VC++\Projects\Split\Split" \
/I"D:\code\VC++\mylib_vc\include" \
/I"D:\code\VC++\Projects\ColorSampleJP\images" \

# ライブラリ(-l)
LIBRARY_l = /DYNAMICBASE "wsock32.lib" "comctl32.lib" \
"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" \
"comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" \
"uuid.lib" "odbc32.lib" "odbccp32.lib" \
"CharExtract.lib" "Funcs.lib" "ColorConvert.lib" "Split.lib"

LIBRARY_l_Debug = "fltkd.lib" "fltk_jpegd.lib" "fltk_imagesd.lib" "fltk_pngd.lib" "fltk_formsd.lib" "fltk_gld.lib" "fltk_zd.lib"
LIBRARY_l_Release = "fltk.lib" "fltk_jpeg.lib" "fltk_images.lib" "fltk_png.lib" "fltk_forms.lib" "fltk_gl.lib" "fltk_z.lib"

# ライブラリパス(-L)
LIBRARY_L = /LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\ATLMFC\lib\x64" \
/LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\lib\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\lib\10.0.22000.0\ucrt\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\\lib\10.0.22000.0\\um\x64" \
/LIBPATH:"D:\code\VC++\mylib_vc\lib"

LIBRARY_L_Debug = /LIBPATH:"C:\packages\fltk-1.3.8\lib\Debug" \
/LIBPATH:"D:\code\VC++\Projects\ColorConvert\x64\Debug" \
/LIBPATH:"D:\code\VC++\Projects\Split\x64\Debug"
LIBRARY_L_Release = /LIBPATH:"C:\packages\fltk-1.3.8\lib\Release" \
/LIBPATH:"D:\code\VC++\Projects\ColorConvert\x64\Release" \
/LIBPATH:"D:\code\VC++\Projects\Split\x64\Release"

# ソースファイル
SRCDIR = .\src
SRCS = $(SRCDIR)\btnAction.cpp $(SRCDIR)\FileChooser.cpp $(SRCDIR)\FileChooser2.cpp $(SRCDIR)\main.cpp \
$(SRCDIR)\modalDialog.cpp $(SRCDIR)\searchLocation.cpp $(SRCDIR)\csvProcessChar.cpp $(SRCDIR)\AddOn.cpp \
$(SRCDIR)\AddOnDialog.cpp $(SRCDIR)\AddOnPurchase.cpp

# オブジェクトファイル
OBJDIR = .\obj
OBJS = $(OBJDIR)\btnAction.obj $(OBJDIR)\FileChooser.obj $(OBJDIR)\FileChooser2.obj $(OBJDIR)\main.obj \
$(OBJDIR)\modalDialog.obj $(OBJDIR)\searchLocation.obj $(OBJDIR)\csvProcessChar.obj $(OBJDIR)\AddOn.obj \
$(OBJDIR)\AddOnDialog.obj $(OBJDIR)\AddOnPurchase.obj

# 実行ファイル
TARGETDIR = .\bin
TARGET = ColorSampleJP.exe

# cppファイルからobjファイル作成 $**:全依存ファイル
# デバッグ
$(OBJS): $(SRCS)
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $(INCLUDE2) $**
	move *.obj $(OBJDIR) >nul

# リリース
# $(OBJS): $(SRCS)
# 	$(COMPILER) $(CPPFLAGS) $(INCLUDE) $(INCLUDE2) $^
# 	move *.obj $(OBJDIR) >nul

# objファイルから実行ファイル作成
# デバッグ
$(TARGET):
	$(LINKER) $(CONSOLE) $(LIBRARY_l) $(LIBRARY_l_Debug) $(LIBRARY_L) $(LIBRARY_L_Debug) $(OBJS) $(LDFLAGS) $(RESOURCE)
	rename btnAction.exe $(TARGET)
	move $(TARGET) $(TARGETDIR) >nul

# リリース
# $(TARGET):
# 	$(LINKER) $(WINDOWS) $(RELEASE) $(LIBRARY_l) $(LIBRARY_l_Release) $(LIBRARY_L) $(LIBRARY_L_Release) $(OBJS) $(LDFLAGS) $(RESOURCE)
# 	rename btnAction.exe $(TARGET)
# 	move $(TARGET) $(TARGETDIR) >nul

# ビルド
.PHONY:all
all: obj $(TARGET)

.PHONY:all2
all2: clean obj $(TARGET)

# objファイル作成
.PHONY:obj
obj: $(OBJS)

# ファイル削除
.PHONY:clean
clean:
	del /Q $(TARGETDIR)\$(TARGET) $(OBJS) vc140.idb vc140.pdb btnAction.pdb

# 変数確認
.PHONY:var
var:
	echo $(SRCS)
	echo $(OBJS)

[C++] 227 Visual C++ : Makefile改良案 clコンパイラ版

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

Makefileでobjファイルを作成する箇所がcppファイル毎にコマンド作成するという非効率な書き方だったので関数を使うなどして改良してみました。

ただしこの内容ではcppファイルが更新されていなくても一括コンパイルしてしまうため、デバッグについては個別に書く方が良さそうです。

話は変わりますが、ライセンス関係を考慮し配布アプリのソースコード公開を回避するには一部のLGPL以外のGPLプログラムを使わないようにする必要があります。

GNU MakeについてはMicrosoft NMAKEに移行します。

# コンパイラ設定他
COMPILER = cl
DEBUG = /D "_DEBUG"
CONSOLE = /SUBSYSTEM:CONSOLE
WINDOWS = /SUBSYSTEM:WINDOWS
LINKER = LINK
RESOURCE = "ColorSampleJP.res"

# オプション設定
CPPFLAGS = /std:c++17 /GS /W3 /Zc:wchar_t /ZI /Gm- /Od /sdl  /Zc:inline /fp:precise /D "_UNICODE" \
/errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /FC /c /diagnostics:column /EHsc
LDFLAGS = /DEBUG /MACHINE:X64 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /OPT:REF /INCREMENTAL:NO

# includeパス(-I)
INCLUDE = /I"C:\packages\fltk-1.3.8\include" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\atlmfc\include" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\cppwinrt" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\ucrt" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\shared" \
/I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Include\um" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt"

INCLUDE2 = /I"D:\code\VC++\Projects\ColorSampleJP\include" \
/I"D:\code\VC++\Projects\ColorConvert\ColorConvert" \
/I"D:\code\VC++\Projects\Split\Split" \
/I"D:\code\VC++\mylib_vc\include" \
/I"D:\code\VC++\Projects\ColorSampleJP\images" \

# ライブラリ(-l)
LIBRARY_l = /DYNAMICBASE "wsock32.lib" "comctl32.lib" \
"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" \
"comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" \
"uuid.lib" "odbc32.lib" "odbccp32.lib" \
"CharExtract.lib" "Funcs.lib" "ColorConvert.lib" "Split.lib"

LIBRARY_l_Debug = "fltkd.lib" "fltk_jpegd.lib" "fltk_imagesd.lib" "fltk_pngd.lib" "fltk_formsd.lib" "fltk_gld.lib" "fltk_zd.lib"
LIBRARY_l_Release = "fltk.lib" "fltk_jpeg.lib" "fltk_images.lib" "fltk_png.lib" "fltk_forms.lib" "fltk_gl.lib" "fltk_z.lib"

# ライブラリパス(-L)
LIBRARY_L = /LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\ATLMFC\lib\x64" \
/LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\lib\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\lib\10.0.22000.0\ucrt\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\\lib\10.0.22000.0\\um\x64" \
/LIBPATH:"D:\code\VC++\mylib_vc\lib"

LIBRARY_L_Debug = /LIBPATH:"C:\packages\fltk-1.3.8\lib\Debug" \
/LIBPATH:"D:\code\VC++\Projects\ColorConvert\x64\Debug" \
/LIBPATH:"D:\code\VC++\Projects\Split\x64\Debug"
LIBRARY_L_Release = /LIBPATH:"C:\packages\fltk-1.3.8\lib\Release" \
/LIBPATH:"D:\code\VC++\Projects\ColorConvert\x64\Release" \
/LIBPATH:"D:\code\VC++\Projects\Split\x64\Release"

# ソースファイル
SRCDIR = .\src
SRCS = $(addprefix $(SRCDIR)\, $(shell dir $(SRCDIR) /b))

# オブジェクトファイル
OBJDIR = .\obj
OBJS = $(addprefix $(OBJDIR), $(patsubst .\src%,%,$(SRCS:.cpp=.obj)))

# 実行ファイル
TARGETDIR = .\bin
TARGET = ColorSampleJP.exe

# cppファイルからobjファイル作成 $^:全依存ファイル
# デバッグ
$(OBJS): $(SRCS)
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $(INCLUDE2) $^
	move *.obj $(OBJDIR) >nul

# リリース
# $(OBJS): $(SRCS)
# 	$(COMPILER) $(CPPFLAGS) $(INCLUDE) $(INCLUDE2) $^
# 	move *.obj $(OBJDIR) >nul

# objファイルから実行ファイル作成
# デバッグ
$(TARGET):
	$(LINKER) $(CONSOLE) $(LIBRARY_l) $(LIBRARY_l_Debug) $(LIBRARY_L) $(LIBRARY_L_Debug) $(OBJS) $(LDFLAGS) $(RESOURCE)
	rename Addon.exe $(TARGET)
	move $(TARGET) $(TARGETDIR) >nul

# リリース
# $(TARGET):
# 	$(LINKER) $(WINDOWS) $(RELEASE) $(LIBRARY_l) $(LIBRARY_l_Release) $(LIBRARY_L) $(LIBRARY_L_Release) $(OBJS) $(LDFLAGS) $(RESOURCE)
# 	rename Addon.exe $(TARGET)
# 	move $(TARGET) $(TARGETDIR) >nul

# ビルド
.PHONY:all
all: obj $(TARGET)

.PHONY:all2
all2: clean obj $(TARGET)

# objファイル作成
.PHONY:obj
obj: $(OBJS)

# ファイル削除
.PHONY:clean
clean:
	del /Q $(TARGETDIR)\$(TARGET) $(OBJS) vc140.idb vc140.pdb AddOn.pdb

# 変数確認
.PHONY:var
var:
	echo $(SRCS)
	echo $(OBJS)

[C++] 226 Visual C++ : ストアアプリのアドオン公開

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

前回の記事から実質5日程度でストアアプリのアドオン公開にこぎつけました。

Windows API、Windows Runtime APIの独特な仕様に終始悩まされました。hstringやPWCHARなどなど文字列データ型やシノニム(同義語)の多さには面食らいましたね。UNIX系プログラマから見ると本当に奇異怪々な世界です。C/C++の学び始めにはMacをお勧めします。

StoreLicense.ExtendedJsonDataのC++での戻り値がhstring型だというのはMicrosoftドキュメントのどこを探しても説明がなく、コンパイル時にclコンパイラから教えられました。まあソースのヘッダファイルを確認すればわかることですが。

アドオンの検証にはライセンスありPC 1台、ライセンスなしPC 1台の2台を使用しました。

アドオンライセンスはMicrosoftアカウントに付与されますが、購入した時のパソコンにその痕跡が残っているかのような挙動を示します。ライセンス管理の実態についてはより突っ込んだ調査が必要でしょう。

アドオン実装でつまずいた所については気が向いたら記事にします。

[C++] 225 Visual C++ : ストアアプリ決済画面への遷移 FLTK

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

ようやく決済画面に遷移できるようになりました。たった十数行のために丸2日掛かりました。

MicrosoftのドキュメントではC#ユーザーに手厚くサポートし、C++ユーザーには仕組みだけ用意して放置です。サンプルコードが圧倒的に不足しています。

結局、Windows kitsにあるcppwinrtのbase.h(約9000行)から必要な関数を自分で探し出しました。

あとStackOverFlow英語版にまたもや助けられました。ここの情報がなかったらもう数日遅れていたでしょう。

次はアドオンの中身を実装してストアに申請し、決済などの検証を行います。

アドオンを登録していないのでMicrosoftログインから先には進めない
アプリ本体(無料)の製品IDで決済画面を呼び出した場合
#include "AddOnPurchase.h"
#include "AddOnDialog.h"
#include <unknwn.h>
#include <iostream>
#include <string>
#include <vector>
#include <winrt/Windows.Services.Store.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <ppltasks.h>
#include <shobjidl.h>

using std::cout; using std::endl;
using std::vector; using std::string;

using namespace winrt;
using namespace winrt::Windows::Services::Store;
using namespace winrt::Windows::Foundation::Collections;
// using namespace winrt::Windows::Foundation; エラーの原因 このnamespaceは使わないこと
using namespace concurrency;
using namespace winrt::impl;

extern vector<string> AddOnLabels;

AddOnPurchase::AddOnPurchase(int w, int h, const char* title)
    : Fl_Window(w, h, title) {

    int ws1, hs1, ws2, hs2; 
    int xs1, ys1, xs2, ys2;

    // ボタンのサイズと位置
    ws1 = 100; hs1 = 50;
    ws2 = 100; hs2 = 50;
    xs1 = 150; ys1 = 390;
    xs2 = 350; ys2 = 390;

    this->color(fl_rgb_color(238, 238, 238));

    // 説明画像
    Fl_Box* img_box = new Fl_Box(20, 12, 560, 360);
    string img_path = "AddOnDescribe.png";
    Fl_PNG_Image *png = new Fl_PNG_Image(img_path.c_str());
    img_box -> image(png);
    img_box -> redraw();

    // Purchaseボタン
    Fl_Button* md_button = new Fl_Button(xs1, ys1, ws1, hs1, AddOnLabels[4].c_str());
    md_button->parent(this);
    md_button->callback(PushButtonPurchase, this);
    md_button->down_box(FL_UP_BOX);
    md_button->labelsize(14);

    // QUITボタン
    Fl_Button* md_button2 = new Fl_Button(xs2, ys2, ws2, hs2, "QUIT");
    md_button2->parent(this);
    md_button2->callback(PushButtonQuit, this);
    md_button2->down_box(FL_UP_BOX);
    md_button2->labelsize(14);

    resizable(this);
    end();
}

AddOnPurchase::~AddOnPurchase()
{
}

void AddOnPurchase::PushButtonPurchase(Fl_Widget* widget, void* x)
{
    Fl_Group* window = widget->parent();
    window->hide();

	// StoreContext取得
    StoreContext _storeContext = StoreContext::GetDefault();

	// StoreContext を IInitializeWithWindow へキャストする
	IInitializeWithWindow* initWithWindow;
	winrt::Windows::Foundation::IInspectable* inspect = reinterpret_cast<winrt::Windows::Foundation::IInspectable*>(&_storeContext);
	HRESULT hr = inspect -> as(IID_PPV_ARGS(&initWithWindow));

	// Fl_Windowのハンドラを決済画面に渡す
	if (!FAILED(hr)){
		extern Fl_Window* window;
        initWithWindow->Initialize((HWND)fl_xid(window));
        initWithWindow->Release();
    } else {
		return;
	}
        
	// 購入手続
	winrt::Windows::Foundation::IAsyncOperation<StorePurchaseResult> _StorePurchaseResult = _storeContext.RequestPurchaseAsync(L"製品ID");
}

void AddOnPurchase::PushButtonQuit(Fl_Widget* widget, void* x)
{
    Fl_Group* window = widget->parent();
    window->hide();
}

参考サイト1
参考サイト2(StackOverFlow英語版)

[C++] 224 Visual C++ : ストアアプリのアドオン用ダイアログ遷移 FLTK

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

カラーアプリのアドオンライセンス確認ダイアログから遷移させて、説明ダイアログを表示するようにしました。

スキル的に特筆することはありませんが、FLTKのlibファイルが不足していたためにFl_PNG_Imageまわりでエラーが大量発生し少々あせりました。Makefileを修正してことなきを得ました。

#include "AddOnPurchase.h"
#include "AddOnDialog.h"
#include <string>
#include <vector>

using std::vector; using std::string;

extern vector<string> AddOnLabels;

AddOnPurchase::AddOnPurchase(int w, int h, const char* title)
    : Fl_Double_Window(w, h, title) {

    int ws1, hs1, ws2, hs2; 
    int xs1, ys1, xs2, ys2;

    // ボタンのサイズと位置
    ws1 = 100; hs1 = 50;
    ws2 = 100; hs2 = 50;
    xs1 = 150; ys1 = 390;
    xs2 = 350; ys2 = 390;

    this->color(fl_rgb_color(238, 238, 238));

    // 説明画像
    Fl_Box* img_box = new Fl_Box(20, 12, 560, 360);
    string img_path = "AddOnDescribe.png";
    Fl_PNG_Image *png = new Fl_PNG_Image(img_path.c_str());
    img_box -> image(png);
    img_box -> redraw();

    // Purchaseボタン
    Fl_Button* md_button = new Fl_Button(xs1, ys1, ws1, hs1, AddOnLabels[4].c_str());
    md_button->parent(this);
    md_button->callback(PushButtonPurchase, this);
    md_button->down_box(FL_UP_BOX);
    md_button->labelsize(14);

    // QUITボタン
    Fl_Button* md_button2 = new Fl_Button(xs2, ys2, ws2, hs2, "QUIT");
    md_button2->parent(this);
    md_button2->callback(PushButtonQuit, this);
    md_button2->down_box(FL_UP_BOX);
    md_button2->labelsize(14);

    resizable(this);
    end();
}

AddOnPurchase::~AddOnPurchase()
{
}

void AddOnPurchase::PushButtonPurchase(Fl_Widget* widget, void* x)
{
    Fl_Group* window = widget->parent();
    window->hide();
}

void AddOnPurchase::PushButtonQuit(Fl_Widget* widget, void* x)
{
    Fl_Group* window = widget->parent();
    window->hide();
}

[C++] 223 Visual C++ : ストアアプリのアドオン用ダイアログ作成 FLTK

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

Microsoftストアアプリのアドオンライセンスの有無をチェックし、ライセンスを購入していない場合に購入画面へ案内するダイアログを作成しました。

購入へ誘導するフローのノウハウが全くないので既存アプリのやり方をこれからチェックします。

いきなり購入ボタンを表示するなど、商売っ気を出してユーザーの方を戸惑わせないように気をつけます

#include <FLstd.h>
#include "modalDialog.h"
#include "AddOnDialog.h"
#include "AddOn.h"
#include <DEBUG_MACRO.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <winrt/Windows.Services.Store.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>

using std::cout; using std::endl;
using std::string; using std::to_string;
using std::vector;

extern Fl_Double_Window* window;
extern vector<string> labels;
extern vector<string> AddOnLabels;
extern bool AddOn1_bool;

extern modalDialog* dlg;
extern AddOnDialog* AddOndlg;

void AddOn1Check(Fl_Widget*, void*) {
    DEBUG_MACRO(AddOn1_bool,Menu_,);

    if (AddOn1_bool == 0) {
        const char* msg = AddOnLabels[1].c_str();
        AddOndlg = new AddOnDialog(400, 200, AddOnLabels[0].c_str(), msg);
        AddOndlg->hotspot(window);

        int x_win = window->x_root();
        int y_win = window->y_root();
        cout << "x_win " << x_win << " y_win " << y_win << endl;

        AddOndlg->resize(x_win + 205, y_win + 165, 250, 150);
        AddOndlg->set_modal();
        AddOndlg->show();

        return;
    } else {
        const char* msg = AddOnLabels[2].c_str();
        dlg = new modalDialog(400, 200, AddOnLabels[0].c_str(), msg);
        dlg->hotspot(window);

        int x_win = window->x_root();
        int y_win = window->y_root();
        cout << "x_win " << x_win << " y_win " << y_win << endl;

        dlg->resize(x_win + 205, y_win + 165, 250, 150);
        dlg->set_modal();
        dlg->show();
    }
}

[C++] 222 Visual C++ : アプリのウィンドウアイコン設定 FLTK

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

ようやくウィンドウアイコンを設定できました。

new演算子でFl_RGB_Imageオブジェクトを作ることにこだわって遠回りしました。new演算子を使わない書き方でようやく成功しました。

今回のは断続的に2日がかりでしんどかったです。一旦諦めた直後にひらめいてあっさり解決しました。FLTKマスターへの道のりはまだまだ遠いです。

まあ仕様が古いといいますかpngファイルのパスだけでアイコン設定できるようにしないとFLTKのユーザーは増えないでしょうね。

以下の手順になります。

1) アイコンのpngファイルをxpmファイルに変換する。フリーのWEBサービス利用可。
2)xpmファイルをエディタで開き、static char*の変数を適当な名前に変える。
3)xpmファイルをincludeして、main関数を以下のように記述する。

#include "icon16.xpm"

Fl_Double_Window* window;

int main(int argc, char** argv) {
    // ウィンドウアイコン設定
    const Fl_Pixmap icon_pix(icon_xpm16);
    const Fl_RGB_Image icon_rgb(&icon_pix);
        
    window = new Fl_Double_Window(50, 50, 660, 480, "COLOR SAMPLE JP");
    window->color(fl_rgb_color(238, 238, 238));
    window->icon(&icon_rgb);

    <以下略>
}
static char *icon_xpm16[] = {
/* columns rows colors chars-per-pixel */
"16 16 14 1 ",
"  c #180614",
". c #006E54",
"X c #016F55",
"o c #ED6D3D",
"O c #EE6D3D",
"+ c #30A36A",
"@ c #3EB370",
"# c #409370",
"$ c #4C9A76",
"% c #1E50A2",
"& c #75B188",
"* c #DAB683",
"= c #CEE4AE",
"- c None",
/* pixels */
"----------------",
"----------------",
"--==  ===....=--",
"--=   ==.+@@@.--",
"--     =.@@@@.--",
"--     =.@@@@.--",
"--==    #.@@XX--",
"--==== ==&..$=--",
"--=Ooo===%====--",
"--ooooo=%%%%==--",
"--oooooo=%%%%%--",
"--oooooo=%%%%%--",
"--ooooo*==%%%=--",
"--=oooo===%%==--",
"----------------",
"----------------"
};

[C++] 221 Visual C++ : 非IDE開発環境 その5 アプリMakefile Debug, Release

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

カラーアプリのMakefileをDebugモード、Releaseモードで実行できるようにしました。

# コンパイラ設定他
COMPILER = cl
DEBUG = /D "_DEBUG"
# DEBUG = 
CONSOLE = /SUBSYSTEM:CONSOLE
WINDOWS = /SUBSYSTEM:WINDOWS
LINKER = LINK
RESOURCE = "D:\code\VC++\Projects\ColorSampleJP\images\ColorSampleJP.res"

# オプション設定
CPPFLAGS = /std:c++17 /GS /W3 /Zc:wchar_t /ZI /Gm- /Od /sdl  /Zc:inline /fp:precise /D "_UNICODE" \
/errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /FC /c /diagnostics:column /EHsc
LDFLAGS = /MACHINE:X64

# includeパス(-I)
INCLUDE = /I"C:\packages\fltk-1.3.8\include" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\atlmfc\include" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include" \
/I"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\ucrt" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\shared" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt" \
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\cppwinrt" \
/I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\Include\um" \
/I"D:\code\VC++\Projects\ColorSampleJP\include" \
/I"D:\code\VC++\Projects\ColorConvert\ColorConvert" \
/I"D:\code\VC++\Projects\Split\Split" \
/I"D:\code\VC++\mylib_vc\include" \
/I"D:\code\VC++\Projects\ColorSampleJP\images"

# ライブラリ(-l)
LIBRARY_l = /DYNAMICBASE "wsock32.lib" "comctl32.lib" \
"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" \
"comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" \
"uuid.lib" "odbc32.lib" "odbccp32.lib" \
"CharExtract.lib" "Funcs.lib" "ColorConvert.lib" "Split.lib"

LIBRARY_l_Debug = "fltkd.lib" "fltk_jpegd.lib" "fltk_imagesd.lib"
LIBRARY_l_Release = "fltk.lib" "fltk_jpeg.lib" "fltk_images.lib"

# ライブラリパス(-L)
LIBRARY_L = /LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\ATLMFC\lib\x64" \
/LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\lib\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\lib\10.0.22000.0\ucrt\x64" \
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\\lib\10.0.22000.0\\um\x64" \
/LIBPATH:"D:\code\VC++\mylib_vc\lib"

LIBRARY_L_Debug = /LIBPATH:"C:\packages\fltk-1.3.8\lib\Debug" \
/LIBPATH:"D:\code\VC++\Projects\ColorConvert\x64\Debug" \
/LIBPATH:"D:\code\VC++\Projects\Split\x64\Debug"
LIBRARY_L_Release = /LIBPATH:"C:\packages\fltk-1.3.8\lib\Release" \
/LIBPATH:"D:\code\VC++\Projects\ColorConvert\x64\Release" \
/LIBPATH:"D:\code\VC++\Projects\Split\x64\Release"

# ソースファイル
SRCDIR = .\src
SRCS = $(SRCDIR)\btnAction.cpp $(SRCDIR)\FileChooser.cpp $(SRCDIR)\FileChooser2.cpp $(SRCDIR)\main.cpp \
$(SRCDIR)\modalDialog.cpp $(SRCDIR)\searchLocation.cpp $(SRCDIR)\csvProcessChar.cpp

# オブジェクトファイル
OBJDIR = .\obj
OBJS = $(OBJDIR)\btnAction.obj $(OBJDIR)\FileChooser.obj $(OBJDIR)\FileChooser2.obj $(OBJDIR)\main.obj \
$(OBJDIR)\modalDialog.obj $(OBJDIR)\searchLocation.obj $(OBJDIR)\csvProcessChar.obj

# 実行ファイル
TARGETDIR = .\bin
TARGET = ColorSampleJP.exe

# cppファイルからoファイル作成 $<:依存ファイル
$(OBJDIR)\btnAction.obj: $(SRCDIR)\btnAction.cpp
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $<
	move btnAction.obj $(OBJDIR) >nul

$(OBJDIR)\FileChooser.obj: $(SRCDIR)\FileChooser.cpp
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $<
	move FileChooser.obj $(OBJDIR) >nul

$(OBJDIR)\FileChooser2.obj: $(SRCDIR)\FileChooser2.cpp
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $<
	move FileChooser2.obj $(OBJDIR) >nul

$(OBJDIR)\main.obj: $(SRCDIR)\main.cpp
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $<
	move main.obj $(OBJDIR) >nul

$(OBJDIR)\modalDialog.obj: $(SRCDIR)\modalDialog.cpp
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $<
	move modalDialog.obj $(OBJDIR) >nul

$(OBJDIR)\searchLocation.obj: $(SRCDIR)\searchLocation.cpp
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $<
	move searchLocation.obj $(OBJDIR) >nul

$(OBJDIR)\csvProcessChar.obj: $(SRCDIR)\csvProcessChar.cpp
	$(COMPILER) $(CPPFLAGS) $(DEBUG) $(INCLUDE) $<
	move csvProcessChar.obj $(OBJDIR) >nul

# oファイルから実行ファイル作成
$(TARGET):$(OBJS)
	$(LINKER) $(CONSOLE) $(LIBRARY_l) $(LIBRARY_l_Debug) $(LIBRARY_L) $(LIBRARY_L_Debug) $(OBJS) $(LDFLAGS) $(RESOURCE)
	rename btnAction.exe $(TARGET)
	move $(TARGET) $(TARGETDIR) >nul

# Releaseモード
# $(TARGET):$(OBJS)
# 	$(LINKER) $(WINDOWS) $(LIBRARY_l) $(LIBRARY_l_Release) $(LIBRARY_L) $(LIBRARY_L_Release) $(OBJS) $(LDFLAGS) $(RESOURCE)
# 	rename btnAction.exe $(TARGET)
# 	move $(TARGET) $(TARGETDIR) >nul

# ビルド
.PHONY:all
all: clean $(TARGET)

# ファイル削除
.PHONY:clean
clean:
	del /Q $(TARGET) $(OBJS) vc140.idb vc140.pdb

[C++] 220 Visual C++ : 非IDE開発環境 その4 アプリアイコン設定

[Windows11, Visual C++2017, FLTK 1.3.8, GNU Make 3.81, NO IDE]

アプリアイコンはMakefileのリンク時のオプションとしてresファイルを入れておけば埋め込まれます。

resファイルはVisual Studioプロジェクトのリソースファイルとしてicoファイルを登録するとビルド時に自動生成します。今回は自製せずにこちらを流用しました。

# コンパイラ設定他
COMPILER = cl
DEBUG = /D "_DEBUG"
CONSOLE = /D "_CONSOLE"
LINKER = LINK
RESOURCE = "D:\code\VC++\Projects\ColorSampleJP\images\ColorSampleJP.res"

<中略>

# oファイルから実行ファイル作成
$(TARGET):$(OBJS)
	$(LINKER) $(LIBRARY_l) $(LIBRARY_L) $(OBJS) $(LDFLAGS) $(RESOURCE) 
	rename btnAction.exe $(TARGET)
	move $(TARGET) $(TARGETDIR) >nul