C# と C++(DLL)を介して「アプリケーション間で連携する方法」を勉強をしています。
●実現したいこと
C# のテキストボックスの値を、DLL で 取得し、別のアプリケーションでその値を利用したい。また、その方法は異なるPCでも同じように動作するようにしたい。
●問題としていること
C# のウィンドウクラス名がPCによって勝手に割り振られてしまい、クラス名が変わってしまう → せっかくつくったDLLが無効となってしまい異なるPCでは使えなくなる。
●疑問&分からないこと
C# のウィンドウクラス名は、あらかじめ設定できるのか? そもそもそんなことは不可能なのか? あるいは、クラス名での文字列検索ではなくこのような場合は、違うアプローチがあるのか?
●解決法として
結局は、どんな方法にしろDLLで文字列を取得できれば良いとは思っています。なので基本的にアプローチはいかなる方法でもよいと思っているのですが、いかんせんWindows API や C++ の深い知識がなくこの先に進めません。試したコードや情報はネット&書籍からのつぎはぎです。(しかし書籍が古すぎてほとんど分からず....)
DLLやメモリ空間を使いたい理由のひとつに高速かつエラーの少ない手法で実現したいと思っていてファイル書き出しなどの遅い処理をせずにできる方法はないかと思っております。
C++及びC#が初心者なため、そもそもできるかどうかも分かりません。なので、おかしなことを言ってるかもしれません。これで同じことができるまたは、解決法がご存じの方はぜひご教示いただけると嬉しいです。
【試した事&疑問 詳細】
FindWindow という Windows API で C# の文字列を取得できる事を知りました。また、これの派生で FindWindowEx という関数にて子ウィンドウの検索もできる事は分かりました、しかしC#のウィンドウクラスは、末尾が勝手に割り振られてしまい、異なるPCではウィンドウクラス名が変わってしまい、DLL で FindWindow クラスを探すコードを書いても使えなくなってしまいます。
(親ウィンドウ クラス名)
WindowsForms10.Window.8.app.xxxxxx
(子ウィンドウ クラス名)
WindowsForms10.EDIT.app.xxxxxx
そして、FindWindow は、親クラスの名前でも検索できるので、仮にC#のフォーム名が Form1 ならフォーム名で探すことはできました。しかし、子ウィンドウは、名前がないのでFindWindowExで「必ずウィンドウクラス名を指定する必要がある」と思います。ですが名前はPCによって変わってしまうという状態です。
そこで思ったのは、あらかじめ「C#側で 子ウィンドウクラス名を指定すれば!?」いいのでは?と思ったのです。しかし、そんなことは方法すらも分からず、、そもそもそんな事出来るのか?とも思います。
以下試したコードです。
C# フォーム側 (ボタンクリックでテキストボックスに1を代入)
/* testForm.cs */ /// <summary> /// ウィンドウ情報 -------------------------------------- ハンドル :1049732(x100484) //ここがテキストボックスクラス名。クラス名は分かるが「Form1」のような名前がない。 //app以降は、親のウィンドウクラスを継承する。 クラス名 :WindowsForms10.EDIT.app.0.141b42a_r10_ad1 タイトル : 位置(左上右下):(498,562,758,632) オーナー : //親ウィンドウクラス名 app 以降はPCまたはタイミング?によって勝手に変わってしまう。 親ウィンドウ : top → bottom hWnd ClassName (Location) Title ----------------------------------------------------------------------- 722040 WindowsForms10.Window.8.app.0.141b42a_r10_ad1 (478,479,778,739) "Form1" 子ウィンドウ ハンドル クラス名 位置(左,上,右,下) 表示文字 ------------------------------------------------------------- /// </summary> // using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace testForm { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int a = 1; //ボタンクリックで、テキストボックスに1を代入する this.textBox1.Text = a.ToString(); } } }
DLL側(親ウィンドウから、子ウィンドウを検索し、子ウィンドウの文字列を返す)
/* findwindw.cpp */ wchar_t *fWindow() { // メモ帳にある文字列を取得した際に、それを格納するバッファ char* pStrBuffer; // 文字列格納用バッファのサイズ long BufferLen; //ウィンドウを探す HWND hWnd = FindWindow(L"WindowsForms10.Window.8.app.0.141b42a_r10_ad1", L"Form1"); if (hWnd != NULL) { //ウィンドウタイトルを取得 char NewName[1040]; GetWindowText(hWnd, (LPWSTR)NewName, 128); //子ウィンドウのウハンドルを取得 HWND hChiWnd = FindWindowEx(hWnd, NULL, L"WindowsForms10.EDIT.app.0.141b42a_r10_ad1", L""); // 子ウィンドウのハンドル取得成功時 if (hChiWnd != NULL) { // メモ帳にある文字列の列長を取得 BufferLen = SendMessage(hChiWnd, WM_GETTEXTLENGTH, NULL, NULL); // 文字端末\0の分をひとつ余計目のサイズに BufferLen = BufferLen + 1; // 文字列格納用バッファの生成 pStrBuffer = (char*)malloc(BufferLen); //文字列を取得して、文字列格納用バッファに設定 SendMessage(hChiWnd, WM_GETTEXT, BufferLen, (LPARAM)pStrBuffer); return (LPWSTR)pStrBuffer; } } return 0; }
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/09/20 15:13
2016/09/30 05:09
2016/09/30 05:12