11-13-2014 08:41 PM
ご協力お願いします。
ウィンドウサイズの変更が可能なアプリケーションを作成する予定です。
フロントパネルに配置するのは表です。表に記述するデータの個数から列数は最大10と
確定しているのですが、行の数がどんどん増える可能性があります。
垂直するクロールバーを追加するので、ただ表示するということであれば問題ないのですが、
離れた行も含めてたくさんの行を確認したいという場合があります。
上記のように列数は変わらないが行数が変更されるという状況なため
ウィンドウサイズで横方向は変更できないが縦方向のみ変更できるようにしたいです。
こんなことは可能でしょうか。
方法があればご回答お願いします。
解決済! 解決策の投稿を見る。
11-15-2014 02:12 PM
こんにちは。
サンプルを作成してみたのでみてみてください。
ちなみにフロントパネル上の表示器のスクロールバーや、VI のスクロールバーも縦横方向に別々に表示を切り替えることができるので、
そういった方法でウィンドウの表示領域を制限することもできます。
11-16-2014 06:11 PM
ご連絡いただき誠にありがとうございます。
サンプルviを動作させてみましたが、上下方向だけでなく左右方向も自由にサイズの変更ができます。
添付するviをお間違えではないでしょうか。
間違っていないということでしたら、こちらの質問文が悪かったと思いますので
改めて記載させていただきます。
最優先事項:ウィンドウサイズの左右方向の変更ができないこと。
優先事項:ウィンドウサイズの上下方向が変更できること。
任意事項:制御器から入力してウィンドウサイズを変更できること。
よろしくお願いします。
11-18-2014 07:33 AM
>> 最優先事項:ウィンドウサイズの左右方向の変更ができないこと。
>> 優先事項:ウィンドウサイズの上下方向が変更できること。
>> 任意事項:制御器から入力してウィンドウサイズを変更できること。
実際には、最後の「制御器から入力してウインドウサイズを変更できること」が一番簡単と思います。
若干計算が要りますが、VIのプロパティノードのFrontPanel-PanelBoundsとWindowBoundsの
4つずつ(上下左右のポジション)を駆使し演算することで、プログラム的に、また、制御器から入力して、
ウインドウサイズは変更できます。
ここでは、元々の(最)優先事項、「ウインドウサイズの左右は変更ができず、上下は変更できること」
を考えてみました。APIをたたく部分でdllを作り、それを併用することで何とか実現できました。
ウインドウのボーダーをつまんでウインドウサイズを変更するのはウインドウメッセージによるもので、
当該VIのウインドウ名(プロパティノードから取得可能)を持つウインドウクラスに、予め、dll 内に
盛り込んでおいた「ウインドウサイズ変更時のコールバック関数(ウインドウプロシージャ)」を設定しておき、
ウインドウズメッセージが送られて来たら、サイズ変更だったらここで有効なレンジを設定してしまうものです。
これにより、その範囲外のサイズには、出来なくなります。
添付の 141118-sample1-FPMinMaxSize.vi は、実行すると、横方向は500pixelのまま動かせません。
縦方向は、150~650pixelの範囲で、サイズ変更できます。実行が終了すると、再び自由にサイズ変更できます。
これは、実行時の最初に、サイズ変更の範囲をしていしてコールバック関数を設定する部分を呼び出しており、
終了時に、それを元に戻す、ということを実行しています。
なお、もう1つの LVFPMinMaxSize.zip は、解凍するとdllになります。
viを開いた時に、dllを探すように言われたら、このdllを選択してください。
「dllがいる」というところが若干スマートではないですが。。
(Windows APIを呼び出すこと自体は、LabVIEWのCall Library Functionで可能なのですが、
コールバック関数を設定する、ということが、LabVIEWの範疇ではできないため)
なお、添付のviは、ver.6なので、もしかしたらお使いのLabVIEWでは古すぎて開けないかも知れません。
当方、OSはWindows 7です。
11-18-2014 07:54 PM
ご連絡いただき誠にありがとうございます。
添付のファイルを確認したところウィンドウサイズに関して希望通りの動作が確認できました。
ただ、ご協力いただいたにもかかわらず誠に申し訳ないのですが、私がやりたい状況では
添付していただいた方法ではエラーが発生してしまい解決には至りませんでした。
とはいえ、ここまでしていただいたことには大きく感謝しております。
ご協力ありがとうございます。
11-19-2014 06:37 AM
おっと、、、エラーが発生してしまいましたですか。。
差支えなければ、どのようなタイプのエラーであるか、お教え頂けますか?
(解決できるかどうかは別にして)
例えば、
・LabVIEWごと、「このアプリケーションは動作を停止しました」などと言って勝手に落ちてしまう
とか、あるいは使い方の面で、当方の確認では実施していない、
・exe化までしたらダメだった? とか
・(ロードはされているが)表示していないviに対してダメだった? とか
そういうレベルではない何らかのエラーであるか・・・
11-19-2014 06:07 PM
ご連絡ありがとうございます。
私のやろうとしていることを少しお話します。
VeriStandのワークスペース上に配置するカスタムワークスペースオブジェクトとして
複数列リストボックスを使用したいと考えています。
※複数列リストボックスに表示する列数が一定だが行数が増える可能性があるため
左右方向は変更できず、上下方向のみ変更したいという考えでした。
カスタムワークスペースオブジェクトはNIのホームページを参考にすると
3種類の作成方法があり、その中の最もカスタマイズ可能なFree Label.viから作成する
方法を選んでいます。
ただ、開発の段階ではウィンドウサイズとして考慮されると思うのですが、
実際に使用する際には、ワークスペース上にオブジェクトとして配置することになる?
そのため、dllからのエラー返り値として4294967295という数値が返ってきてしまい
左右サイズも自由に変更できてしまう状況です。
フロントパネル名称の使用方法が異なるのか良くわかりませんが、
この状況に無理に時間をかけるのもあまりよくないと思っています。
11-20-2014 07:20 AM
なるほど、VeriStand で使用というところで、普通に(?)LabVIEWで動かすのと違いが出てくるのでしょうかね・・・
とりあえず、ここの部分に深入りしないという感じのようですが、一応エラーの考察だけすると、
「dll からのエラー返り値として 4294967295 という数値が返ってきてしまい」とあるので、
どちらの dll 呼び出しもこの値を返しうるのですが、おそらく Unregister の方で出たのだろうと思います。
・最初の Register で、ウインドウプロシージャの設定ができなかった。
・そのため、dll 内部で「自前のプロシージャ設定中」を表すスイッチがONにならず、
・実行中は、上下も左右もサイズ変更が出来てしまい(設定できていないので)、
・最後に Unregister で、「自前のプロシージャの設定がONじゃないのに Unregister しようとした」のでエラー4294967295(0xFFFFFFFF)
という感じなのかな・・・と思います。
(自前エラーの番号をかえておけば、どちらで出たのかはっきりするのですが、同じ値にしてしまいました)
ご参考まで、dllのソースを記しますと、
#include <windows.h>
// cl -LD LVFPMinMaxSize.cpp -link User32.lib Gdi32.lib
__declspec(dllexport) DWORD _stdcall RegisterWindowSizeRange(LPCTSTR, LONG, LONG, LONG, LONG);
__declspec(dllexport) DWORD _stdcall UnregisterWindowSizeRange(LPCTSTR);
LONG vXmin, vXmax, vYmin, vYmax;
int sw=0;
WNDPROC PrevWndProc;
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
LPMINMAXINFO lpmm;
switch(iMsg){
case WM_GETMINMAXINFO:
lpmm=(LPMINMAXINFO)lParam;
lpmm->ptMinTrackSize.x=vXmin;
lpmm->ptMinTrackSize.y=vYmin;
lpmm->ptMaxTrackSize.x=vXmax;
lpmm->ptMaxTrackSize.y=vYmax;
return(0);
}
return(CallWindowProc(PrevWndProc, hWnd, iMsg, wParam, lParam));
}
DWORD _stdcall RegisterWindowSizeRange(LPCTSTR lpWindowName, LONG Xmin, LONG Xmax, LONG Ymin, LONG Ymax)
{
HWND hWnd;
DWORD err;
if(!sw){
vXmin=Xmin;
vXmax=Xmax;
vYmin=Ymin;
vYmax=Ymax;
hWnd=FindWindow(NULL, lpWindowName);
PrevWndProc=(WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc);
err=GetLastError();
if(PrevWndProc){
sw=1;
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
}
} else {
err=0xFFFFFFFF; // already set
}
return(err); // if 0 success
}
DWORD _stdcall UnregisterWindowSizeRange(LPCTSTR lpWindowName)
{
HWND hWnd;
DWORD err;
if(sw){
hWnd=FindWindow(NULL, lpWindowName);
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PrevWndProc);
err=GetLastError();
} else {
err=0xFFFFFFFF; // not set
}
sw=0;
return(err); // if 0 success
}
で、Register の実行時、最初は基本的に sw=0 なので、プロシージャを設定しようとして
・ウインドウ名からウインドウハンドル hWnd を取得し ・・・ここで失敗していると、hWnd が NULL になる
・その hWnd に、自前のプロシージャを設定し ・・・ここで失敗していると、返り値 PrevWndProc が NULL になる
・成功していれば、PrevWndProc は「もともと設定されていたプロシージャ」のアドレスなので NULL で返ることはないので、
・もし、PrevWndProc が NULL だったら、設定できなかったということで、sw は ON しない。
という感じで、sw=0 のままになり、何も設定されていない、という感じです。
(ただし、この場合、エラーコード=GetLastError() 関数の返り値で、4294967295 になることはない)
sw=0 のまま Unregister しようとすれば、おかしいので、Unregister は即座に 4294967295 を返します。
・・・この辺は、ウインドウ名からウインドウハンドルの取得ができていないかも知れないし、
VeriStandなので何か事情が違う、ということもあるかも知れず、これ以上分からないので、
一応分析だけして、このへんにしておきます。