DOBON.NET どぼん!のVB道掲示板(プログラム)過去ログ

ウィンドウのサイズ及び表示位置

御世話になります。
VBをはじめたばかりの超初心者です。(やりたいことは満載なのですが…)

どぼんさんのVB.NET Tipsにありました、"ファイルを関連付けられたソフトで開いて終了まで待機"を参考にさせていただいています。
ファイルを開くことは出来るのですが、開いたファイルの、ウィンドウのサイズ及び表示位置の調整の調整が上手くいきません。
Windowプロパティを用いればよいのでしょうか。。。

おそらく、基本的なことなのだと思いますがお教え願えませんでしょうか?
宜しくお願いいたします。
>どぼんさんのVB.NET Tipsにありました、"ファイルを関連付けられたソフトで開いて終了まで待機"を参考にさせていただいています。
>ファイルを開くことは出来るのですが、開いたファイルの、ウィンドウのサイズ及び表示位置の調整の調整が上手くいきません。
>Windowプロパティを用いればよいのでしょうか。。。
>
>おそらく、基本的なことなのだと思いますがお教え願えませんでしょうか?
>宜しくお願いいたします。

これが意外と「基本的なこと」ではなく、多分APIを使わないと無理なのではないかと思います。

「ファイルを関連付けられたソフトで開いて終了まで待機」にある方法で起動したアプリのウィンドウ位置と大きさを変えるには、APIのMoveWindowを使うことになるでしょう。このときウィンドウハンドルが必要となりますが、これはProcess.MainWindowHandleプロパティで取得できるでしょう。

もしかしたらAPIのCreateProcessを使ったほうがいいかもしれません。
どぼんさんありがとうございます。

>これが意外と「基本的なこと」ではなく、多分APIを使わないと無理なのではないかと思います。

質問させていただいて以降もずっと調べていたのですが、APIを使わないとだめなのかな?というところまではたどり着いていたのですが…、APIとなるとなかなか敷居が高くて。。(必要なときはほとんど、紹介されているものをそのまま使うしかなく…勉強しなくては)

>「ファイルを関連付けられたソフトで開いて終了まで待機」にある方法で起動したアプリのウィンドウ位置と大きさを変えるには、APIのMoveWindowを使うことになるでしょう。このときウィンドウハンドルが必要となりますが、これはProcess.MainWindowHandleプロパティで取得できるでしょう。
>
>もしかしたらAPIのCreateProcessを使ったほうがいいかもしれません。

MoveWindow及びCreateProcessについて色々と調べてみます。
APIとなるとこの掲示板からは外れてしまいますね。(残念です)

もしよろしければ、APIを独習するのにおすすめの書籍・Webページ等ご存知でしたらお教えいただけませんでしょうか?

質問につぐ質問で申し訳ありません。
>どぼんさんありがとうございます。
>
>>これが意外と「基本的なこと」ではなく、多分APIを使わないと無理なのではないかと思います。
>
>質問させていただいて以降もずっと調べていたのですが、APIを使わないとだめなのかな?というところまではたどり着いていたのですが…、APIとなるとなかなか敷居が高くて。。(必要なときはほとんど、紹介されているものをそのまま使うしかなく…勉強しなくては)
>
>>「ファイルを関連付けられたソフトで開いて終了まで待機」にある方法で起動したアプリのウィンドウ位置と大きさを変えるには、APIのMoveWindowを使うことになるでしょう。このときウィンドウハンドルが必要となりますが、これはProcess.MainWindowHandleプロパティで取得できるでしょう。
>>
>>もしかしたらAPIのCreateProcessを使ったほうがいいかもしれません。
>
>MoveWindow及びCreateProcessについて色々と調べてみます。
>APIとなるとこの掲示板からは外れてしまいますね。(残念です)
>
>もしよろしければ、APIを独習するのにおすすめの書籍・Webページ等ご存知でしたらお教えいただけませんでしょうか?
>
>質問につぐ質問で申し訳ありません。

えぇぇ、ちょっと乱入、失礼します。(.NETについては素人なもので・・・)
APIは得意なんですが、.NETは時間がなくて全然調べられません。そもそも、VS.NETを持っているわけではないので、Win2000に.NET Framework SDKを入れる以外調べる術もないのですが・・・。

でも、超初心者さん、いままでの話からすると、APIといっても、MoveWindow()を調べれば十分な気がします。恐らく、CreateProcessまでは要らないでしょう。
もし、Process.MainWindowHandleで、起動したアプリのWindow Handleが取得出来るのなら、それをそのままMoveWindow()に渡すだけなので、とても簡単なはずです。ただし、本当に目的のWindowのハンドルが得られるなら、です。私が思うには、Process.MainWindowHandleって、自プロセスのメインウィンドウのような気がします。
また、CreateProcessを使うと、起動したアプリのプロセスハンドルは確かに得られますね。でも、そこからMainWindowのHandleを得るAPIは、、、覚えていません・・・済みません。そういう意味では「あのWindowのサイズ変える」というのはとても大変なのです。目的のWindowを探してきて、そのハンドルを得るというのはそれほど難しいのです。

逆にProcess.MainWindowHandleで、いとも簡単にそれが得られるなら実に単純です。
>えぇぇ、ちょっと乱入、失礼します。(.NETについては素人なもので・・・)

いつもお世話になって助かります。

私が前回「もしかしたらAPIのCreateProcessを使ったほうがいいかもしれません。」と書いたのは、CreateProcessを使えば確かウィンドウの位置とサイズを指定して実行ファイルを起動できたような気がしたからです。これに対してMoveWindowを使う方法では、アプリを起動してからウィンドウが作成されるまで待機し、それからMoveWindowを使う必要がありそうだからです。ただし、CreateProcessでは実行ファイルしか起動できない欠点はあります。

ちょっと調べてみたところ、「vbvbvb.com」でVB6のコードがありました。「ウィンドウの位置とサイズを指定して実行可能ファイルを起動する」とのことです。

http://www.vbvbvb.com/jp/gtips/0351/gCreateProcess.html

どちらにせよ、Kamaliさんがおっしゃるように確実に目的のウィンドウが操作されるかという保障はないでしょう。

>>もしよろしければ、APIを独習するのにおすすめの書籍・Webページ等ご存知でしたらお教えいただけませんでしょうか?

上で紹介した「vbvbvb.com」をはじめ、VB6でAPIを使う方法を紹介したサイトはたくさんありますので、これらを参考にして書き換えるのが今のところは一番いい方法ではないでしょうか。

MoveWindowを使った例を書いてみました。起動してちょっと間があってからウィンドウが変更されます。

Private Declare Function MoveWindow Lib "user32" Alias "MoveWindow" (ByVal hwnd As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Integer) As Integer

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim p As Process = Process.Start("notepad.exe")
p.WaitForInputIdle()
MoveWindow(p.MainWindowHandle.ToInt32(), 0, 0, 500, 500, 1)
End Sub
Kamaliです。お世話になっております。

>>えぇぇ、ちょっと乱入、失礼します。(.NETについては素人なもので・・・)
>
>いつもお世話になって助かります。
>
>私が前回「もしかしたらAPIのCreateProcessを使ったほうがいいかもしれません。」と書いたのは、CreateProcessを使えば確かウィンドウの位置とサイズを指定して実行ファイルを起動できたような気がしたからです。これに対してMoveWindowを使う方法では、アプリを起動してからウィンドウが作成されるまで待機し、それからMoveWindowを使う必要がありそうだからです。

どぼんさんに指摘されて思い出しました。確かにCreateProcessには、起動時のWindow状態を指定することができます。私はいつもそれをデフォルト値でしか使っていませんが。

>ただし、CreateProcessでは実行ファイルしか起動できない欠点はあります。

そうそう、実行ファイル、しかもフルパス指定でないと動かない。

どぼんさんのTipsより:
>System.Diagnostics.Process.Start("C:\test.txt")

これだけで関連付けられたアプリを使ってファイルを開けるんですかぁ。便利だぁ。
この感覚でCreateProcessを使うのは極めて困難ですね。まず関連付けられたアプリへのフルパスを得る方法から調べて行かなければならないですから。

>ちょっと調べてみたところ、「vbvbvb.com」でVB6のコードがありました。「ウィンドウの位置とサイズを指定して実行可能ファイルを起動する」とのことです。
>
>http://www.vbvbvb.com/jp/gtips/0351/gCreateProcess.html
>
>どちらにせよ、Kamaliさんがおっしゃるように確実に目的のウィンドウが操作されるかという保障はないでしょう。

いえ、私の早とちりのようです。多分、どぼんさんの説明した方法で十分です。

>>>もしよろしければ、APIを独習するのにおすすめの書籍・Webページ等ご存知でしたらお教えいただけませんでしょうか?
>
>上で紹介した「vbvbvb.com」をはじめ、VB6でAPIを使う方法を紹介したサイトはたくさんありますので、これらを参考にして書き換えるのが今のところは一番いい方法ではないでしょうか。
>
>MoveWindowを使った例を書いてみました。起動してちょっと間があってからウィンドウが変更されます。
>
>Private Declare Function MoveWindow Lib "user32" Alias "MoveWindow" (ByVal hwnd As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Integer) As Integer
>
>Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
> Dim p As Process = Process.Start("notepad.exe")
> p.WaitForInputIdle()
> MoveWindow(p.MainWindowHandle.ToInt32(), 0, 0, 500, 500, 1)
>End Sub

このコーディングを参考にさせて頂くと、私が心配しているような「実は自プロセスだった」などという心配は無用のようですね。Processクラスが指しているのは、新たに起動した側のプロセスのようです。

・Process.Start("notepad.exe")

・System.Diagnostics.Process.Start("C:\test.txt")
に置き換えればほぼ完成というところではないでしょうか?
どぼんさん・Kamaliさんありがとうございます。

Kamaliさん10日にも書き込みをいただいていたのに、そのままにしてしまいまして、失礼いたしました。

CreateProcessについて
>>ただし、CreateProcessでは実行ファイルしか起動できない欠点はあります。
>
>そうそう、実行ファイル、しかもフルパス指定でないと動かない。

そのようですね。フルパスに関しては問題ないのですが、今回開きたかったのは、実はExcelのブックだったもので。。
ただ、超初心者の私としてはとても勉強になりました。
本当にやりたいことが山ほどありますので、いつの機会か必ず役に立つものと思います。

>>ちょっと調べてみたところ、「vbvbvb.com」でVB6のコードがありました。「ウィンドウの位置とサイズを指定して実行可能ファイルを起動する」とのことです。
「vbvbvb.com」のご紹介ありがとうございます。(勉強させてもらいます)

>>MoveWindowを使った例を書いてみました。起動してちょっと間があってからウィンドウが変更されます。
不勉強ながら、似たような形のところまではたどり着くことができました。
どぼんさんにいただいた例、Kamaliさんにいただいた指摘を踏まえて、もう一度よく見てみます。

お二方とも本当に貴重な時間を割いていただき誠にありがとうございます。
これからも、何かとお世話になることがあるかとは思いますが、宜しくお願いいたします。
CreateProcessを使って試しにやってみたのですが、notepadをはじめほとんどのアプリで位置もサイズも指定した値が無視されました。CreateProcessは使えなさそうです。
>CreateProcessを使って試しにやってみたのですが、notepadをはじめほとんどのアプリで位置もサイズも指定した値が無視されました。CreateProcessは使えなさそうです。

そうですか。。。
実は確認するのが面倒で説明はしませんでしたが、起動される側のアプリケーションが起動時にどのようにCreateWindow()を実行するかによっては、こちらからの指定が無視される恐れがあって、確実な方法とは言えないのです。特に、MS-Officeのように、自分自身で前回のWindow状態を復元しようとするアプリは当然ですが、全部無視されてしまうでしょう。

CreateProcessに渡すSTARTUPINFOは、だいたい以下のように値をセットしますよね。

Dim StartupInfo As STARTUPINFO
with StartupInfo
.dwFlags = STARTF_USEPOSITION Or STARTF_USESIZE Or ...
.dwX = x
.dwY = y
.dwXSize = w
.dwYSize = h
end with

CreateProcess:
http://www.microsoft.com/japan/developer/library/default.asp?URL=/japan/developer/library/jpwinpf/_win32_createprocess.htm

STARTUPINFO:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/startupinfo_str.asp

これで、左上が(x,y)、サイズが(w,h)のWindowになる筈なんですが、これは飽くまで、起動された側がメインウィンドウをCreateWindowするとき、そこに指定する(x,y,w,h)をCW_USEDEFAULTにしてくれないことにはどうにもなりません。

CreateWindow:
http://www.microsoft.com/japan/developer/library/default.asp?URL=/japan/developer/library/jpuipf/_win32_createwindow.htm

でも、幸いにもプロセスハンドルhProcessからメインウィンドウ・ハンドルが取得できるので、それを使って強制的にサイズを変えるのが最後に残された方法ということになりますね。
こんにちは、超初心者です。
更なる回答等いただきまして誠にありがとうございます。

>前回のWindow状態を復元しようとするアプリは当然ですが、全部無視されてしまうでしょう。
やはり、ここがネックになってしまうんですね。

>でも、幸いにもプロセスハンドルhProcessからメインウィンドウ・ハンドルが取得できるので、それを使って強制的にサイズを変えるのが最後に残された方法ということになりますね。

あれから色々と試してみました。

いつでも、どこでもというわけには行かないのですが、1つこんな方法で試してみました。
ExcelのブックのWorkbook_Open()に対してFindWindow()及びMoveWindow()を書いてみました。
APIの参照は標準Moduleに書きました。

マクロにデジタル署名を付与し、その署名を利用するパソコンに”信頼のおける発行元”として登録しました。
一応、これでできるようにはなっているのですが…
(Excelのほうでフォームとか使い出すと問題が…)

どこでもいつでもというわけにはいきませんし、もっと勉強してみます。
本当にありがとうございます。

何にしても険しい道であることを改めて実感いたしました。

DOBON.NET | プログラミング道 | プログラミング掲示板