• ベストアンサー

API,PathIsDirectoryについて

よろしくお願いします。 VB6.0sp6,Windows2000professionalsp4です。 VBでのディレクトリの有無の判別方法を検索していて、サンプルをひとつ見つけたのですが・・・↓がコードです。 ------------------------------------------------ Private Declare Function PathIsDirectory Lib "SHLWAPI.DLL" Alias "PathIsDirectoryA" _ (ByVal pszPath As String) As Long ' ' ディレクトリであるかどうか ' Private Function IsDirectory(ByVal strFileName As String) As Boolean ' strFilename : チェックしたいディレクトリ名 ' 戻り値 : ディレクトリであればTrueを返す。 Dim lngResult As Long lngResult = PathIsDirectory(strFileName) IsDirectory = Not (lngResult = 0) 'ここが理解できません End Function Private Sub Command1_Click() Dim strFileName As String strFileName = "C:\WINNT\Profiles\Administrator\My Documents\HEROPA\TestCls\SHLWAPI" Msgbox IsDirectory(strFileName) End Sub -------------------------------------------- IsDirectory関数は、PathIsDirectoryの戻り値がLong型のため、それをBooleanに直すためのものだと思うのですが、 IsDirectory = Not (lngResult = 0)はどういう原理なのでしょうか? これだとlngResultにどんな値が入ろうがIsDirectoryに返されるのはTrueになってしまうと思うのですが(lngResultに0が代入され、それがNotされるから)、しかし実際に実行してみるとちゃんとTrueとFalseを判定しています。いったいどうしてなのでしょうか? それと、PathIsDirectoryの宣言で、関数の戻り値がLongになっていますが、他に見つけたサンプルではBooleanとなっていました。どちらが正しいのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.9

>VBでのTrueは-1という理解でいいのでしょうか?それとも0以外という理解が正しいのでしょうか? 値としては、-1です。 ただ、Trueを固定値概念で持つ必要はありません。 False(0)でなければ、Trueの分岐部が走ります。 だから「VBでのTrueは」というより「VBでのTrue値は」であれば、確かに-1です^^; そういう認識を持っていれば、言語を意識しないで済むと思いますよー 最初の発言に戻りますが、 >PathIsDirectoryの宣言で、関数の戻り値がLongになっていますが、他に見つけたサンプルではBooleanとなっていました。どちらが正しいのでしょうか? PathIsDirectory自体は、DLLに用意されれある関数ですよね? 自分で作成したものではなく、既に用意されているDLLの関数を、どのように利用するかというのがAPIの宣言です。 他の例ですが(ちょっと例えが悪いかもしれませんが)、 Declare Function API関数 Lib "HOGEHOGE.DLL" (ByRef パラメータ As 構造体) As Long と切る場合もあれば Declare Function API関数 Lib "HOGEHOGE.DLL" (ByVal パラメータ As Long) As Long と切るパターンもあります 結果としては、どっちでもいいです。 この例のAPI関数においてはパラメータ部で、構造体の先頭ポインタさえ渡れば、どっちでもいいわけです。 この関数を利用する人の利用したいように宣言ができます。 戻り値部分にいたっては、もっと融通が利きます。 Cに渡す部分であれば、DLLが欲しているパラメータなので、ある程度の制約が発生しますが、戻り値はこっちが受ける部分なので、DLLがその戻り値に対し、メモリを参照することはありません。 私の持っているMSDNでは BOOL PathIsDirectory(   LPCTSTR pszPath   ); と書いてあるので、2つの固定値を返す関数のようですね。 さらに0と16を返すようです。 16が返るからといって、わざわざこれをLongで受けて、 If (Long戻り値=16) Then なんてやる人はいませんよね^^; そこでキャストして受けるようにしてあげれば、Longの概念が打ち消せるわけです。 ちなみにCで利用するパターン(参考までにです) http://nienie.com/~masapico/api_PathIsDirectory.html (確か海外のVBのサイトだったと思うけど)Win32APIタイプライブラリというのが存在しています。 それを参照すると、APIの宣言をしなくてもよいという代物です。 そのタイプライブラリはAPIビューワと、結構違います^^; APIビューワだけが正ではありません。 たくさんAPI利用のサイトを見たらわかると思いますが、みんな結構バラバラですよね^^; 私に限らず、結構オリジナルでやる人が、今では多いと思いますよー IN/OUT/戻り値を意識していれば、正しいパターンは複数あります。 計算ドリルと違って、正解は一つじゃないのです。 結果、PathIsDirectoryの戻りは、BooleanであろうとLongであろうと、間違いはありません。 どういう宣言が、一番目的に適しているかで、自分で扱いやすい方を選択したらいいと思いますよ。

tochanx
質問者

お礼

ほぼ理解できました。何度も回答していただき本当にありがとうございます! ところで、最近のプログラミング雑誌には、VB6.0の記事はほぼ見られなくなりました。.netを購入する財布も、気力もない私としてはつらいです。6.0もまだまともに使えないのに.netに移ってもしかたありませんしね。 思えばこれまでいろいろな言語を、つついては放り、放ってはつつきとなんだかうじうじやってきました。結果、あまりにも自分の持つ知識が使い物にならないかを実感する毎日です。 もっとがんばらねば、と思いました。 どうもありがとうございました!

その他の回答 (8)

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.8

>>>C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。 >>とありますが、VBでも一緒です。 >VBは違いますよ(^^; 例えばですが If 9999 Then   MsgBox "True 処理" Else   MsgBox "False 処理" End If とすると、TRUE処理が走ります 9999に限らず0以外ならTRUE処理となります。 >確かに、CBool()ではゼロ以外をTrueと判定してくれますが、 >試しにイミディエイトウインドウで >?Cint(true) >?Clng(True) >としてみてください。 >この場合のイコールは「一対一」という意味です。 それを言うと、キリがないのですが、 CではTrueをintにキャストしたら、1なのですが。。。 CやVBに限らず、[FALSE=0] というのは、私の知る限りでは「プログラミング言語」全体的にそうなのではないでしょうか? Trueを判定するより、Falseを判定する方が処理ステップが少なく済む場合が多いです。(直近の業務がアセンブラだったので^^;) 簡素な言語レベルでそうなので、その上をいく近代言語でも、基本的なルールは変わらないと思います。 上記例でも If 9999 Then の中では [9999]は[0]ではないから という処理が予想できます。 if (9999) {   MessageBox (0,"true処理","",MB_OK); } else {   MessageBox (0,"false処理","",MB_OK); } これはCでも一緒ですよね^^; さらに別例も揚げておきます。 Cでの永久ループ while (《0以外の整数値》) { }; VBでの永久ループ Do While (《0以外の整数値》) Loop >これを「気持ち悪い(Boolean型への暗黙のキャストなので)」と取るか、「使えればOK」と取るかはその人次第なのかもしれませんが、私個人としては「基本をきっちり押さえること」が大事だと思ってます。 はい、それは非常にわかります。私も当初は「暗黙のキャスト」は非常に疑問を覚えました。 しかしそれを利用する事で、ステップ数の削減を行えるので、VBの利点として逆手に取ることもできます。 >ですから、「誉められない」と書いたのです。 もう、これは価値観かな^^;

tochanx
質問者

お礼

>Trueを判定するより、Falseを判定する方が処理ステップが少なく済む場合が多いです 貴重な情報をありがとうございます。脳に刻みました。 すみません。混乱してきました。VBでのTrueは-1という理解でいいのでしょうか?それとも0以外という理解が正しいのでしょうか?

  • piyo2000
  • ベストアンサー率49% (144/293)
回答No.7

#6さんは、結構お出来になる方みたいですね(^^; >私も、宣言はオリジナルでやっちゃいます。 私も、個人で作っているプログラム(で、かつソースを公開しない)ならそうすると思います。 ただ、仕事で使ったり他の人にソースを流用される可能性がある場合は、少なくともコメントは入れると思います。 実際に、tochanxさんが「なぜここはBooleanなのだろう」と疑問をもたれてますよね。これは可読性を失った結果・・・だと思うのです。 >>C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。 >とありますが、VBでも一緒です。 VBは違いますよ(^^; 確かに、CBool()ではゼロ以外をTrueと判定してくれますが、 試しにイミディエイトウインドウで ?Cint(true) ?Clng(True) としてみてください。 この場合のイコールは「一対一」という意味です。 MS-Basicで良く、論理式でTrueの場合は-1を返すということを利用して i = (k > 0)*(-20) + 80 みたいな式を書いたことがある人は、BasicでのTrue(真)は-1ということを良く知っているんですけどね(^^; # もっとも、今こんな式を書いたら怒られてしまいますけど(^^; 前に戻って、もしPathIsDirectoryが「0か-1か」を返す関数であればBooleanで全く問題ないですね。 # BOOLなので0か1か、かもしれませんけど ですが実際に(Longで宣言した上で) debug.print PathIsDirectory("C:\") としてみてください。 # 私の環境では16が出力されました これを「気持ち悪い(Boolean型への暗黙のキャストなので)」と取るか、「使えればOK」と取るかはその人次第なのかもしれませんが、私個人としては「基本をきっちり押さえること」が大事だと思ってます。 ですから、「誉められない」と書いたのです。 ちょっとキツイ内容になってしまいましたが、私も敵意があるわけではないのでご容赦を(^^;

tochanx
質問者

お礼

お礼が遅れてしまい申し訳ありません。 なるほど!理解が少し深まりました。ありがとうござます! 確かにCint(true),Clng(true)の結果はともに-1になりますね。VBではTrueは-1ということですね。 すみません。ちょっとわからないのですが、 >この場合のイコールは「一対一」という意味です というのはどういう意味なのでしょうか? 私の環境でも16が出力されました。

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.6

#5さんに一部賛同で一部反論(敵意ではないのでご容赦を) >PathIsDirectoryの宣言で、関数の戻り値がLongになっていますが、他に見つけたサンプルではBooleanとなっていました。 >どちらが正しいのでしょうか? まず、どちらが正しいという考えはありません。 APIの宣言は、関数ではなく「宣言」です。 それよりLongかBooleanかを問いてますが、その部分は返し値部分なので、 「返す値の範囲を理解する事」 「どのような利用の仕方をするか」 というのが大事だと思います。 APIにまだ不慣れなら、#5さんが述べられているような方法をお勧めいたします。 でも慣れたら、教科書通りのやり方をする必要はありません。私も、宣言はオリジナルでやっちゃいます。 ただ、ここの掲示板で書くときは、APIビューワの宣言から利用します。 #5さんの発言どおり、掲示板なので >可読性 を重視した内容にするためです。 突然ですが、APIサンプルの超有名なURL vbvbvb.com http://www.vbvbvb.com/ ぱぱんぶいびぃ http://www.mitene.or.jp/~sugisita/ Visual Basic Station http://www1.harenet.ne.jp/~unaap/ かなりヘビーなAPI使い師です。 各サンプルは、パラメータであればほとんど一緒ですが、戻り値にいたっては宣言方法がみんな一緒とは限りません。 またvbvbvb.com運営者とぱぱんぶいびぃ運営者が登録しているVBのメーリングリストが存在しています。 これまたヘビーなメーリングリストで、回答がC++で返ってくることもあるようなところです。 そこでも、戻り値の型を意識するより、APIの特性に意識するように結論が出ていました。 要は「せっかくのVBなんだから、使えればOK」って感じだと思います。 パラメータではないので、PathIsDirectoryの戻り値の取る範囲から、メモリリークを意識しないでもいい事は明らかです。 あと#5さんへの補足 >また#2さんが指摘されていらっしゃるように >VBでは「True=-1」「False=0」なわけですが >C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。 とありますが、VBでも一緒です。 #2さんが >しかし、実際には >Not 0→True と言っている部分があります。その部分のことですね。 vbvbvb.com のサンプルの多くは、これを意識したAPI関数の利用になっていると思います。

tochanx
質問者

お礼

お礼が遅れて申し訳ありません。 どうもありがとうございます! 非常に勉強になります。教科書に書いていないことばかりで、とてもわくわくします。 リンクまでたくさん提示していただき、本当に助かります。 vbvbvb.comには以前いったことがあるのですが、挫折してしまいました・・・ すみません。一ヶ所理解できないところがあります。もしよろしければ補足をお願いしたいです。 >パラメータではないので、PathIsDirectoryの戻り値の取る範囲から、メモリリークを意識しないでもいい事は明らかです。 ここが理解できません。戻り値の取る範囲から、メモリリークを意識する必要がないとはどういうことなのでしょうか? 回答ありがとうございました!

  • piyo2000
  • ベストアンサー率49% (144/293)
回答No.5

>どちらが正しいのでしょうか? #1さんが#3で指摘されておられるように「Long」です。 というより、API関数の殆どの戻り値はHANDLEにしろポインタにしろ(VB内部では)Longで帰ってきます。 >他に見つけたサンプルではBooleanとなっていました。 は、単にこのケースで言うと「Declare宣言だけでIsDirectoryと同じ事を実現する」為だと思います。 手抜きといっては手抜きですが、こういうのはあまり誉められませんね(^^; まあ、イミディエイトウインドウで ?CBool(1) ?Cbool(0) とでもしてみれば分かると思いますが、この関数に関しては0なら失敗、それ以外なら成功なので実害はありませんけど。 また#2さんが指摘されていらっしゃるように VBでは「True=-1」「False=0」なわけですが C/C++やAPI関数の戻り値では基本的に「False=0」「True=0以外」です。 IsDirectory = Not (lngResult = 0) という表現は、これを意識してのことだと思いますよ(^^; # C/C++で良く # if (!hoge()){... # と書くのと一緒かと。 #1さんが「Boolean型のサイズが変わるかもという話」をされていますが、これはC/C++では考慮しないといけない話ではありますが、VB6ということであれば考える必要は全くありませんね。 そもそも64BitプラットフォームではVB6なんて使えないでしょうし・・・(^^; >計算量が少なくて効率的な気がするのですが 現在のコーディングでは、効率より可読性を大事にするケースのほうが多いと思いますし、そうすべきだと思います。 (lngResult <> False) では、もしlngResultがBooleanだったらそんな書き方はせずに (lngResult) または (lngResult = True) と書きますよね。 それに、そもそもlngResultはLong、True/FalseはBooleanですから、違う型で比較するのは直感的に嫌な感じがします(^^;

tochanx
質問者

お礼

どうもありがとうござます! ?は自動的にPrintに変換されるんですね! 大変示唆に富んだ内容で、とても勉強になりました!

回答No.4

「<>」 私もそうなのですが、一部の人が嫌います。 これはおそらく、他の言語ではあまり見かけないからじゃないかなー Cやオラクルのストアドプロシージャでは !(A=B) と書いて同じ意味を持ちます。 IsDirectoryはAPIを内部で利用しているだけのオリジナル関数だから、返しの型は結局何でもいいです。 ただIsDirectory関数の特性として ・ある ・ない を返すだけなので、Boolean特性にしているのでしょう。 また、 Not (lngResult = 0) この表現はよく用いられる書き方です。 APIの定数で API_FALSE = 0 です。 API関数の戻り値のパターンをあげておきます (1)存在チェック系など ・[0]存在しない ・[-1]存在する (2)実行系など1 ・[0]失敗 ・[正値]成功(1以上の長整数) (3)実行系など2 ・[負値]失敗(エラー番号) ・[正値]成功(1以上の長整数) (4)実行系など3 ・[正値]失敗(1以上の長整数で特定のエラー番号) ・[正値]成功(1以上の長整数で特定の正常ステータス値) などなど、いっぱいあります。 (1)のパターンのAPIであれば、全て Not (lngResult = 0) でステータスを、わかりやすいBoolean型に置き換えることが可能です。

tochanx
質問者

お礼

慣習なんですね。勉強になります。 わざわざAPI戻り値のパターンまで教えていただき、ありがとうございます!

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

>プログラミング的にはVBにおけるPathIsDirectoryの宣言では、戻り値の型はBooleanにする方がよいというのは… すみません、ちょっと調べてみたのですが、 VB6での Boolean型は、サイズが2バイトで Long型は、4バイト SHLWAPI.DLLでの戻り値 BOOL型は、4バイトですので、 型を合わせるということで言えば、Long型の方がいいですね。ごめんなさい。 >Booleanが将来的に他の型を使われる可能性 紛らわしい表現だったかもしれません。 他の型というのは、Boolean型のサイズが変わるかもという話です。(よく考えてみればLong型にしても同じことが言えますね^^;) Boolean型は、VB6では、前述したように、2バイトサイズですけど、将来的に、(例えば64ビットマシンが基本的なコンピュータとなった時に?、)4バイトになったりあるいは、1バイトになったりする可能性があります。なので、そうした物理的なサイズを指定するより、抽象的な型名を使う方が良いというような意味でした。(今回の質問の場合逆になってしまいました(;^_^A ) ちなみに、VCでは、 BOOL型はint(4バイト)で BOOLEAN型は、char(1バイト)になっていました。

tochanx
質問者

お礼

なるほど、理解できました。 懇切に解説して頂き感謝の極みです。 まことにありがとうございました!

回答No.2

0→False です -1→True です しかし、実際には Not0→True です Not (lngResult = 0) ↓ Not (lngResult = False) ↓ (lngResult <> False) という意味です。

tochanx
質問者

お礼

ありがとうござます。 しかしどうして、 Not (lngResult = 0) と (lngResult <> False) が同じ式なのにNotの方を採用しているのでしょうか? Not (lngResult = 0) と (lngResult <> False) なら、 (lngResult <> False) の方が計算量が少なくて効率的な気がするのですが・・・

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

VB言語では、 lngResult = 0 は、位置によって代入の場合と論理式の場合があります。 質問文の場合、論理式として評価されます。 なので、代入されるのではなく、0かどうかを調べて、true か falseになります。 IF文で0かどうか調べるときXXX = 0と条件の部分にかきますよね、それと同じです。 >PathIsDirectoryの宣言で、… APIの説明を観るとBOOL型となっていました。 結局BOOL型の実体がLONG(VBでの)ということなのでしょう 同じコト(最終的に同じものになる場合)でも、 プログラミング的には、Booleanの方がいいのだと思います。(Booleanが将来的に他の型を使われる可能性がありますから)

tochanx
質問者

お礼

ありがとうございます。 位置によって論理式として評価されるのですか!なるほど!納得です。 ですが、BLUEPIXY様の回答の後半部分が理解できません。 プログラミング的にはVBにおけるPathIsDirectoryの宣言では、戻り値の型はBooleanにする方がよいというのはわかりましたが、()の中の「Booleanが将来的に他の型を使われる可能性がありますから」というのがわかりません。 よろしければもう少しわかりやすく教えていただけないでしょうか?ヒントだけでもお願いします。

関連するQ&A

  • APIを使う時は参照設定は不要?

    例えば Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Sub test() Dim Handle As Long Handle = FindWindow("IEFrame", vbNullString) Debug.Print Handle End Sub と言うコードでウィンドウハンドルを取得する場合、 参照設定のどこにもチェックを入れませんが、なぜ参照設定しなくても使えるのでしょうか? Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long が参照設定の代わりになるのですか?

  • 64ビットエクセルでのAPI宣言/PtrSafe

    エクセルのInputboxで、入力された文字列を自動的にアスタリスクで隠すようにする方法を探し http://okwave.jp/qa/q2371878.html の回答No1のコードがまさに最適なコードで、これまで非常に助かっていました。 ところが、64bitのエクセルでは動かないことがわかりました。 表示されたエラーメッセージの言葉から調べて、PtrSafeという言葉を入れなければならないようなのでAPI宣言を以下のようにしてみました。 #If VBA7 And Win64 Then '64ビット版 Private Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _ (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long Private Declare PtrSafe Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" _ (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _ ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long #Else '32ビット版 Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _ (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" _ (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _ ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long #End If ところが、回答No1のコードで Sub Report_Open() を実行すると Public Function InputBoxDK(Prompt, Optional Title, Optional Default, Optional XPos, _ Optional YPos, Optional HelpFile, Optional Context) As String のところがハイライトされてエラーになります。 どう直せば良いのでしょうか? 全文のコードを乗せると字数制限に引っかかりますので、申し訳ありませんが宣言以外の部分は http://okwave.jp/qa/q2371878.html の回答No1のコードを見てくださいますようお願いします。

  • APIについて

    Private Declare Function GetComputerName Lib "kernel32.dll" Alias _ "GetComputerNameA" (ByVal NameBuff As String, ByVal Size As Long) As Long Public Sub New() mstrMyCompName = Me.QryComputerName() mstrMyDummyData = mstrMyCompName & mcstrDumyKey End Sub Public Function QryComputerName() As String Dim strTmp As String Dim lngPos As Long If 0& < GetComputerName(strTmp, 256) Then lngPos = InStr(strTmp, vbNullChar) QryComputerName = Left$(strTmp, lngPos - 1) Else QryComputerName = "UnKnown" End If End Function 上記の記述を含むクラスを生成した際に、GetComputerName(strTmp, 256)のところで下記のエラーが発生しますが、原因が分かりません。 'System.NullReferenceException' のハンドルされていない例外が AtnSys.exe で発生しました。 追加情報 : オブジェクト参照がオブジェクト インスタンスに設定されていません。 何がいけないのでしょうか? OS:Win2000 言語:VB.Net ソリューション名:AtnSys

  • VBA ウィンドウの列挙 Win32 API

    http://d.hatena.ne.jp/cartooh/20090618 上記のページに記載されているVBAです。 動作は確認できたのですが、どのような処理の流れとなっているのかがわかりません。 どなたかコメントを付けていただけないでしょうか。 よろしくお願いいたします。 Option Explicit Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal cnm As String, ByVal cap As String) As Long Declare Function IsWindowVisible Lib "user32" (ByVal hWnd As Long) As Long Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, _ ByVal cch As Long) As Long Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, _ ByVal lParam As Long) As Long Declare Function IsWindow Lib "user32" (ByVal hWnd As Long) As Long Const INDENT_KEY = "INDENT" Public Function EnumChildWindowsProc(ByVal hWnd As Long, ByVal lParam As Object) As Long EnumChildWindowsProc = EnumWindowsProc(hWnd, lParam) End Function Public Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Object) As Long EnumWindowsProc = True If IsWindowVisible(hWnd) = 0 Then Exit Function End If Dim strClassName As String ' * 255 Dim strCaption As String ' * 255 strClassName = String(255, vbNullChar) strCaption = String(255, vbNullChar) GetWindowText hWnd, strCaption, Len(strCaption) GetClassName hWnd, strClassName, Len(strClassName) strCaption = RTrim(left(strCaption, InStr(1, strCaption, vbNullChar) - 1)) strClassName = RTrim(left(strClassName, InStr(1, strClassName, vbNullChar) - 1)) ActiveCell.Cells(1, 1).Value = Hex(hWnd) ActiveCell.Cells(1, 2).Value = IsWindowVisible(hWnd) ActiveCell.Cells(1, 3).Value = strCaption ActiveCell.Cells(1, 4).Value = strClassName ActiveCell.Cells(2, 2).Activate Dim c As Collection Set c = lParam Dim indent As Long indent = c(INDENT_KEY) c.Add String(indent * 2, " ") & Hex(hWnd) & " " & strCaption & " " & strClassName, before:=c.Count indent = indent + 1 c.Remove INDENT_KEY c.Add indent, INDENT_KEY Call EnumChildWindows(hWnd, AddressOf EnumChildWindowsProc, ObjPtr(c)) indent = c(INDENT_KEY) - 1 c.Remove INDENT_KEY c.Add indent, INDENT_KEY ActiveCell.Cells(1, 0).Activate End Function Sub hoge() Application.ScreenUpdating = False Dim sht As Worksheet Set sht = ThisWorkbook.Worksheets(1) sht.UsedRange.Clear sht.Activate sht.Range("A1").Activate Dim c As Collection Set c = New Collection c.Add 0, INDENT_KEY Dim ret As Long ret = EnumWindows(AddressOf EnumWindowsProc, ObjPtr(c)) c.Remove INDENT_KEY Set sht = ThisWorkbook.Worksheets(2) sht.UsedRange.Clear sht.Activate sht.Range("A1").Activate Dim o As Variant For Each o In c ActiveCell.Value = o ActiveCell.Cells(2, 1).Activate Next Application.ScreenUpdating = True End Sub

  • API FtpPutFileの戻り値

    お世話になっております。 API FtpPutFileを使用しているのですが 確実にFalseになります。一日悩みましたが原因が わかりません。 If FtpPutFile(lngConnect, _ "***.txt", _ "***.txt", _ FTP_TRANSFER_TYPE_ASCII, _ 0&) <> False Then です。必要なものを付け加えておきます。 Private Declare Function FtpPutFile Lib "wininet.dll" _ Alias "FtpPutFileA" _ (ByVal hFtpSession As Long, _ ByRef lpszLocalFile As String, _ ByRef lpszNewRemoteFile As String, _ ByVal dwFlags As Long, _ ByVal dwContext As Long) As Long Private Const FTP_TRANSFER_TYPE_ASCII = &H1& です。環境はWinXP,VB6+SP5 よろしくお願い致します。

  • VB6 APIを使った文字印刷について

    VB6でAPI(TextOut)を使って印刷する必要があるのですが、インターネットで調べたらサンプルがあってそれを参考にさせてもらおうと思っています。 ただ、当方としては、印刷位置と印刷文字サイズをmmで指定したく、色々試しているのですがうまくいきません。お分かりになる方どこがおかしいかご教示願えないでしょうか? サンプルのソースコードを以下に張っておきます。formにCommandボタンを一つ張ってください。 Option Explicit Dim FX As Integer 'フォントの横サイズ Dim FY As Integer 'フォントの縦サイズ Dim cx As Long '表示X座標 Dim cy As Long '表示Y座標 Private Const DEFAULT_CHARSET = 1 Private Const OUT_DEFAULT_PRECIS = 0 Private Const DEFAULT_QUALITY = 0 Private Const DEFAULT_PITCH = 0 Private Const FF_DONTCARE = 0 Private Const LF_FACESIZE = 32 Private Type Size cx As Long cy As Long End Type Private Type LOGFONT lfHeight As Long lfWidth As Long lfEscapement As Long lfOrientation As Long lfWeight As Long lfItalic As Byte lfUnderline As Byte lfStrikeOut As Byte lfCharSet As Byte lfOutPrecision As Byte lfClipPrecision As Byte lfQuality As Byte lfPitchAndFamily As Byte lfFaceName(LF_FACESIZE) As Byte End Type Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long Private Declare Function CreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long Private Declare Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32A" (ByVal hdc As Long, ByVal lpsz As String, ByVal cbString As Long, lpSize As Size) As Long Private Sub Command1_Click() Printer.Print "" '文字印刷位置縦0mm 文字幅6mm、文字高6mmで印刷 FX = 6: FY = 6 cx = 0: cy = 0 PrintText "testてすと1" '文字印刷位置縦50mm 文字幅6mm、文字高12mmで印刷 FX = 6: FY = 12 cx = 0: cy = 50 PrintText "testてすと2" '縦倍角 '文字印刷位置縦200mm 文字幅12mm、文字高6mmで印刷 FX = 12: FY = 6 cx = 0: cy = 100 PrintText "testてすと3" '横倍角 Printer.EndDoc End Sub Sub PrintText(text As String) Dim LF As LOGFONT Dim IX As Integer Dim TempByteArray() As Byte Dim ByteArrayLimit As Long Dim OldFT As Long Dim NewFT As Long Dim rtn As Long Dim hdc As Long Dim PX As Long Dim PY As Long hdc = Printer.hdc '↓(1)ここで文字印刷位置をmmかTwipに変換しているつもりなのですが・・・ PX = Printer.ScaleX(cx, vbMillimeters, vbTwips) PY = Printer.ScaleY(cy, vbMillimeters, vbTwips) With LF .lfEscapement = 0 '文字の回転角度(角度*10) '↓(2)ここで文字サイズをmmかTwipに変換しているつもりなのですが・・・ .lfHeight = Printer.ScaleY(FY, vbMillimeters, vbTwips) '文字の高さ .lfWidth = Printer.ScaleX(FX, vbMillimeters, vbTwips) '文字の幅 .lfWeight = 400 '文字の太さ .lfItalic = False '斜体 .lfUnderline = False '下線 .lfStrikeOut = False '取り消し線 .lfCharSet = DEFAULT_CHARSET .lfOutPrecision = OUT_DEFAULT_PRECIS .lfClipPrecision = OUT_DEFAULT_PRECIS .lfQuality = DEFAULT_QUALITY .lfPitchAndFamily = DEFAULT_PITCH Or FF_DONTCARE TempByteArray = StrConv("MS ゴシック", vbFromUnicode) ByteArrayLimit = UBound(TempByteArray) For IX = 0 To ByteArrayLimit .lfFaceName(IX) = TempByteArray(IX) Next End With NewFT = CreateFontIndirect(LF) OldFT = SelectObject(hdc, NewFT) TextOut hdc, PX, PY, text, LenB(StrConv(text, vbFromUnicode)) rtn = SelectObject(hdc, OldFT) rtn = DeleteObject(NewFT) End Sub 以上よろしくおねがいします。

  • VBAでSetTextColorがうまくいかない

    EXCELのVBAでユーザーフォームを使ったグラフィック表示のプログラムを 作っているのですが、SetTextColorでテキスト色の設定をしようと してもうまくいきません。何故か設定しようとする色の値が無視されて 「1304008」が設定されてしまいます。(GetTextColorで確認) そしてそれ以降何を設定してもこの状態のままです。 何か考えられることがありますでしょうか。 下にそのプログラムを示します。 ちなみにSetBKColorやAngleArcなど他のグラフィック命令は問題なく 動いていてSetTextColorだけがうまくいってない状態です。 '------------------------------------------------- ' ユーザーフォーム用プログラム '------------------------------------------------- Private Declare Function GetActiveWindow Lib "user32" () As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpszClass As String, _ ByVal lpszWindow As String) As Long Private Declare Function GetDC Lib "user32" ( _ ByVal hWnd As Long) As Long Private Declare Function ReleaseDC Lib "user32" ( _ ByVal hWnd As Long, _ ByVal hdc As Long) As Long Private Declare Function SetTextColor Lib "gdi32" _ (ByVal hdc As Long, crColor As Long) As Long Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" _ (ByVal hdc&, ByVal x&, _ ByVal y&, ByVal lpString$, ByVal nCount&) As Long Dim hWnd As Long Dim hdc As Long Public Sub UserForm_Activate() DoEvents hWnd = FindWindowEx(GetActiveWindow, 0, "F3 Server 60000000", "") hdc = GetDC(hWnd) ret = SetTextColor(hdc, RGB(255, 0, 0)) ret = TextOut(hdc, 0, 0, "abc", 3) Call ReleaseDC(hWnd, hdc) End Sub '-------------------------------------------------

  • IMEの単語登録について

    テキストボックスに文字を入力して、確定と同時にIMEの単語登録辞書を表示せずに、辞書に登録するプログラムを作っているのですが、うまく出来ずにいます。途中のプログラムを載せますので間違いがありましたら教えていただけないでしょうか? Private Declare Function GetKeyboardLayout_ Lib "user32" (ByVal idThread As Long) As Long_ Private Declare Function ImmRegisterWord_ Lib "Imm32.dll" Alias "ImmRegisterWordA" _ (ByVal hKL As Long, ByVal lpszReding As String,_ ByVal dwStyle As Long, ByVal lpszRegisterAs_ String) As Long Private Sub Label6_Click() Dim hKL As Long Dim lpszReading As String '単語の読み Dim lpszRegister As String '単語の語句 Dim dwStyle As Long '単語の品詞   hKL = GetKeyboardLayout() lpszReading = Text1.Text 'Text1に入力された            単語をlpszReadingに格納 lpszRegister = Text1.Text 'Text1に入力された            単語をlpszRegisuterに格納 ImmRegisterWord hKL, lpszReading, dwStyle,       lpszRegister '読み・語句をIME辞書に登録 End Sub です。よろしくお願いします。

  • WinAPIで電卓をクリック

    現在、WinAPIを勉強しており、練習としてVBAを用いて、電卓アプリのボタンをクリックしようとしています。 キーを送るのではなく、クリックで行いたいたいと 考えています。 ボタンのハンドルを取得するところまではできましたが、sendMessageでクリックできず、EditBoxに数字が 入りません。 どのようにすればよいのかご教授ください。 よろしくお願い致します。 環境: WinXP home、 Excel2002、Win付属アプリの電卓v5.1 ---作成したプログラム---- '標準モジュールの中身 Option Explicit Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hWnd As Long) As Long Private Const WM_LBUTTONDOWN = &H201 Private Const WM_LBUTTONUP = &H202 Sub Main() Dim lngWindWnd As Long 'ウィンドウハンドル Dim ret As Long Dim hCalc As Long 'アプリケーションタイトルより、ウィンドウハンドルを得ます lngWindWnd = FindWindow(vbNullString, "電卓") '8ボタンのハンドル(確実に取れていることを確認 hCalc = FindWindowEx(lngWindWnd, 0, "Button", "8") ret = SetForegroundWindow(lngWindWnd) ret = SendMessage(hCalc, WM_LBUTTONDOWN, 0, 0) End Sub

  • APIって

    VBで簡単なプログラムを作成しています。 APIも便利なのでサンプルを見ながら使っていますが ふと疑問に思ったので教えて下さい。 以下の"advapi32.dll"と"ADVAPI32"の違いは何なのでしょうか。 大文字、小文字の違いだけで同じなのですか? dllを省略すると引数に&をつけるつけないの違いが出るのでしょうか? 'レジストリの値を取得する Public Declare Function RegQueryValueExstr Lib "ADVAPI32" Alias "RegQueryValueExA" (ByVal hKey&, ByVal lpValueName$, ByVal lpReserved&, ByVal lpType&, ByVal lpData$, lpcbData&) As Long 'レジストリの値を設定する Public Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpData As Any, ByVal cbData As Long) As Long ネット上にたくさんサンプルはあるので、やりたいことの方法を調べてできればOKといったやり方です。 きちんと勉強したい気持ちもありますので、参考書籍等紹介して頂いてもうれしいです。