Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.1 ) |
- 名前:紺帽子 日時:2020/10/11 13:11
LoadGraphなどはカレントディレクトリの影響を受けたと思います。
ファイルをプログラムにドラッグすると、そのファイルのディレクトリがカレントディレクトリになるかと思います。
その場合はプログラムからの相対パスで画像などを読み込んでいると失敗します。
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.2 ) |
- 名前:たろう 日時:2020/10/11 14:19
重要な情報をありがとうございます<(_ _)>
ドラッグしたファイルの場所がカレントディレクトリになるのは全然知りませんでした…
ウィンドウズの仕様なんでしょうけれど、なんでそんなことになっているのでしょう
起動時にファイルの情報を受け取れたとしても
exeファイルの位置を保存しておいて読み込むすべてのパスをそれに基づいて変更するような作業が
必要になりそうですね、ファイルの情報を受け取る部分もまだうまくいっていませんが
頂いた情報をもとにもう少し調べてみます<(_ _)>
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.3 ) |
- 名前:たろう 日時:2020/10/11 15:40
おかげ様で、頂いた情報から色々調べて
一応ディレクトリの問題は、画像読込前にこれ↓を呼ぶ事で何とかなりそうです
int exepath()
{
char pt[MAX_PATH];
GetModuleFileNameA(NULL, pt, sizeof(pt)/sizeof(pt[0]));
char *p;p = strstr(pt,"実行ファイル名.exe");*p ='\0';SetCurrentDirectory (pt);
return 0;
}
進捗でした<(_ _)>
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.4 ) |
- 名前:はるかぜ 日時:2020/10/11 16:08
exeにドラッグ&ドロップしたファイルの情報は
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
↑これのlpCmdLineに渡されてくるはずです
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.5 ) |
- 名前:紺帽子 日時:2020/10/11 16:13
カレントディレクトリを実行ファイルの場所に設定して、渡されたファイル名を取得する簡素なプログラムです。
起動時に渡したファイル名はコマンドライン引数として渡されてくるので、WinMain()の3番目の引数やGetCommandLine関数を使用できます。
今回は、__argc, __argv を使うのが一番楽だと思います。
#include "DxLib.h"
#include <vector>
// PathRemoveFileSpec のため
#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// 起動時のカレントディレクトリを表示のため保存しておく
std::vector<char> startDir(1024);
GetCurrentDirectory(startDir.size(), &startDir[0]);
// 実行プログラムのパスをバッファにとる
std::vector<char> newDir(__argv[0], __argv[0] + strlen(__argv[0]) + 1);
// 末尾のパス区切り文字とファイル名を取り除く
PathRemoveFileSpec(&newDir[0]);
// カレントディレクトリを設定する
SetCurrentDirectory(newDir.data());
// DXライブラリ初期化
ChangeWindowMode(TRUE);
if (DxLib_Init() == -1) { return -1; }
// 起動時のカレントディレクトリを表示する
printfDx("Old : %s\n", startDir.data());
// 現在のカレントディレクトリを表示する
printfDx("New : %s\n", newDir.data());
// プログラム名と受け取ったファイル名を出力する
for (int i = 0; i < __argc; ++i) {
printfDx("%d : %s\n", i, __argv[i]);
}
printfDx("\n");
// キー待ち
WaitKey();
return 0;
}
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.6 ) |
- 名前:たろう 日時:2020/10/11 17:08
はるかぜさん、ありがとうございます<(_ _)>
たしかにlpCmdLineにパスがそのまま入っているようで、これを使えそうです。
紺帽子さん、サンプルまでありがとうございます
起動させていただきましたところ、放り込んだファイルのパスが得られました。
PathRemoveFileSpecというものがあるのも初めて知りました。勉強になります<(_ _)>
ただ、現状utf8で作っている都合上、lpCmdLineもそうですが、得られる情報はs-jisなようで
これをプログラム上で使うには変換が必要です。
頂いたサンプルは、これは全く私のせいなのですがレベルが高すぎるようで、
std::vector<char>あたりの事が全く理解できませんので
上記問題を解決するために修正して使うのは、現状無理と思われます。
自分自身の能力的な限界を元に一番近そうな解決策は、lpCmdLineで得られた情報をUTF8に変換する
ということになろうかと思っていますが、この点なにか方法をご存知の方がいらっしゃれば、
ヒントだけでも結構です、頂けると助かります。
自分でも調べてみます。
※std::vector<char>の知識も、ちょっと勉強してみます<(_ _)>
表題とずれてしまって申し訳ありません<(_ _)>
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.7 ) |
- 名前:紺帽子 日時:2020/10/11 22:19
カレントディレクトリ変更などのWindowsAPIを使用するときはUNICODE文字列とUNICODE版のAPIを使用します。
UTF8のコマンドライン引数が欲しいときはUNICODE版関数で引数を取得してからUNICODE文字列をUTF8文字列に変換しています。
以下のプログラムなら実行ファイルに落としたパスもUTF8で取得できると思います。
#include "DxLib.h"
#include <locale.h>
#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")
// コマンドライン引数用の構造体
struct CommandArgs {
int Argc;
char **Argv;
};
// コマンドライン引数をUTF8に変換して格納する
void CommandArgs_Init(CommandArgs & Args)
{
// UNICODE版コマンドライン引数を取得する
int Length;
LPWSTR* CommandLine = CommandLineToArgvW(GetCommandLineW(), &Length);
// 引数の数についてバッファを確保
Args.Argc = Length;
Args.Argv = new char*[Length];
for (int i = 0; i < Length; ++i) {
// UNICODE文字列をUTF8文字列に変換したときのバッファサイズを取得する(ヌル文字分含む)
int Bytes = ConvertStringCharCodeFormat(Get_wchar_t_CharCodeFormat(), CommandLine[i], DX_CHARCODEFORMAT_UTF8, NULL);
// UTF8文字列のバッファ確保
Args.Argv[i] = new char[Bytes];
// UNICODE文字列をUTF8文字列に変換する
ConvertStringCharCodeFormat(Get_wchar_t_CharCodeFormat(), CommandLine[i], DX_CHARCODEFORMAT_UTF8, Args.Argv[i]);
}
// UNICODE版コマンドライン引数を解放する
LocalFree(CommandLine);
}
// CommandArgsを解放する
void CommandArgs_End(CommandArgs & Args)
{
for (int i = 0; i < Args.Argc; ++i) {
delete[] Args.Argv[i];
}
delete[] Args.Argv;
Args.Argc = 0;
}
// カレントディレクトリを実行ファイルの場所にセットする
void SetCDToProgramDir()
{
// UNICODE版コマンドライン引数を取得する
int Length;
LPWSTR* CommandLine = CommandLineToArgvW(GetCommandLineW(), &Length);
// ディレクトリのバッファ確保
wchar_t * ProgramDir = new wchar_t[lstrlenW(CommandLine[0]) + 1];
// 文字列コピー
lstrcpyW(ProgramDir, CommandLine[0]);
// 末尾のパス区切り文字とファイル名を取り除く
PathRemoveFileSpecW(ProgramDir);
// カレントディレクトリを設定する
SetCurrentDirectoryW(ProgramDir);
// ディレクトリのバッファ解放
delete[] ProgramDir;
// UNICODE版コマンドライン引数を解放する
LocalFree(CommandLine);
}
// 文字列のバイトを表示する
void PrintBytes(const char *Line)
{
const size_t n = strlen(Line);
for (size_t i = 0; i < n; ++i) {
if (i != 0 && (i % 16) == 0) { printfDx(u8"\n"); }
printfDx(u8"%02X ", (unsigned char)Line[i]);
}
printfDx(u8"\n");
}
// メイン処理
void DxLibMain(const CommandArgs & Args)
{
for (int i = 0; i < Args.Argc; ++i) {
printfDx(u8"(%d): %s\n", i, Args.Argv[i]);
PrintBytes(Args.Argv[i]);
}
WaitKey();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// UTF8の設定
if (!setlocale(LC_ALL, ".utf8")) { return -1; }
SetUseCharCodeFormat(DX_CHARCODEFORMAT_UTF8);
// カレントディレクトリをプログラムの場所へ
SetCDToProgramDir();
// コマンドライン引数をUTF8に変換する
CommandArgs Args;
CommandArgs_Init(Args);
// DXライブラリ初期化
ChangeWindowMode(TRUE);
SetGraphMode(1280, 720, 32);
if (DxLib_Init() == -1) { return -1; }
// メイン処理
DxLibMain(Args);
// コマンドライン引数オブジェクトを破棄する
CommandArgs_End(Args);
// DXライブラリ終了
DxLib_End();
return 0;
}
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.8 ) |
- 名前:たろう(解決) 日時:2020/10/11 22:41
はるかぜさん 紺帽子さん、ありがとうございました
結局その後、s-jisからutf-16 utf-16からutf8という非常に回りくどい方法で
変換できることが分かったのですが、
直後思い立ってこの掲示板を検索してみましたところ
ConvertStringCharCodeFormat( DX_CHARCODEFORMAT_SHIFTJIS, lpCmdLine, DX_CHARCODEFORMAT_UTF8, tx) ;
という関数を発見しました。これを使うと望み通りの結果が得らましたので
まだ試してはいないのですが全ての条件がそろったので問題なくドラッグ&ドロップで起動できると思います。
というわけで解決とさせていただきたいと思います。
本当に何でもそろっているDXライブラリに感謝します<(_ _)>
ありがとうございました
|
Re: 実行ファイルに直接ファイルをドラッグ&ドロップして起動する方法 ( No.9 ) |
- 名前:たろう(解決) 日時:2020/10/11 22:55
紺帽子さん…すみません
文章を書いているうちに重なってしまったようです。
またサンプルを、しかも私でも理解できそうな簡易な書き方をしていただいてありがとうございます
既に解決とさせていただきましたが、頂いたサンプルはとても参考になりますので
しっかり理解して、今後に生かしていきたいと思います。
本当にありがとうございました<(_ _)><(_ _)>
|