戻る 2019/06/05 23:45:31


0001 ファイルのIOを行う方法
0002 コンボボックスでIMEMODEプロパティーを使用するときの注意
0003 クラスモジュールの要点
0004 Single型は、恐くて使えない。
0005 コマンドボタンの不思議なバグ。
0006 計算の精度
0007 INIファイルの制限
0008 Val関数
0009 Fix関数の謎。
0010 関数の引数の制限。
0011 ユーザー定義型とFRMモジュールの制限
0012 ダイアログフォーム
0013 項目移動をエンターkeyで行うGUIを設計するときの注意。
0014 VBから印刷を行う時に、EXCELを使用する上での注意。
0015 隣接するテキストボックスA、Bで、Aの入力内容により、Bを入力可、不可に切り替える方法
0016 [ALT]+[TAB]で表示される候補
0017 あるフォーム(A)から、ダイアログフォーム(B)を表示。この時(A)上のマウスポインターを砂時計にし、(B)上のマウスポインターは既定値にする方法。
0018 SSパネルでフォーカスを持つと、IMEが制御不能になる。
0019 MultiLine Trueのテキストボックスの制限
0020 dir関数の制限
0021 LSet関数の制限
0022 App.Pathの定義
0023 Shell起動した画面フォームがアクティブにならない?
0024 相対パス指定時の注意
0025 OLE(ACTIVE X)
0026 インストール ウィザード(ver 4.0) 配布ファイルを手動で追加する時に相対ディレクトリを指定する方法。
0027 レジストリ登録について
0028 DDEのTOPICに何を編集するか
0029 長い名前のVBPファイルをopenすると、短い名前に変化されてしまう。
0030 BEEPがならないとき
0031 App.Exenameの注意
0032 よく使用するonerrコード
0033 処理中にボタンクリックイベントを無効にするときの問題点
0034 For Eachを利用したフォーム上のコントロールの初期化
0035 NULLについて
0036 タブダイアログコントロールのバグについて
0037 VisualBasicから裏でAccessを制御するときの制限
0038 誤差について
0039 メニューバーのあるフォームの初期表示位置
0040 開発環境で実行中の無限ループより、復帰するには
0041 半角文字と全角文字てピッチを揃えたいときには
0042 ユーザーイベントの実装例
0043 フォームにエクセルを貼り付ける基本
0044 フォームオブジェクトについての考察
0045 テンプレート
0046 IDEのショートカット
0047 VBのメモリー管理って、ガベージコレクション
0048 オプションボタンのグループ化ってどうやるか?
0049 隠し関数のメモ
0050 VBの配列はCとは内部構造が違うぞ!
0051 コントロールを動的に増やして配置する
0052 クラスのメソッドは、スタティックメソッドは実装できるのか?
0053 強制リブートの考察
0054 Collection型には、ユーザー定義型は入らないのか?
0055 フォームからアイコンを消す方法
0056 ON ERRORの内容が消えてしまう?
0057 DLLが見つからない! エラー53
0058 フォームのアイコンのメンテナンスを簡単に行うには
0059 VBではGetLastErrorは使えない
0060 VB6でも、WindowsXP Lookは実現できる
0061 スクリーンセーバー動作中に、メッセージボックス?
0062 シェルコマンドをプログラムから起動する方法
0063 EXE分割されても、親よりも必ず手前に表示されるモーダレスダイアログのように振る舞うフォームの実装方法
0064 コマンドライン引数の制限はどのくらいか?
0065 四捨五入と丸め
0066 VBでも継承ができる?
0067 タブコントロールの不思議
0068 メッセージボックスが2つでるケース
0069 画面サイズとディスプレーのサイズ
0070 void型のDLLをVBから呼び出す時の型は?

0001    ファイルのIOを行う方法

文字化けの概念

VB2.0では、UNICODEのようなものは存在していなかったので問題はなかったが、VB4.0ではUNICODEが内部で採用されているので、注意が必要になる。

 
    Lenb(“あいう”)は、6
              
    Len(“あいう”)は、3
              
    Lenb(“あい1”)は、6
              
    Len(“あい1”)は、3              

である。UNICODEは半角文字も全角文字も、1文字を現わすのに2バイト必要である。

Line Input #1, TextLine

これは、改行までを、 TextLineに読み込むステートメントである。
しかしTextLineはstring型等の単項目である必要がある。半角と全角が混在する場合、 TextLineをユーザー定義型を利用して複数項目に分解するのは困難である。

Open "TESTFILE" For Random As #1 Len = Len(MyRecord)
Get #1, Position, MyRecord

これは、Lenで指定されたバイト数分、 ユーザー定義体MyRecordに読み込みを行う。 ユーザー定義体の中に固定長文字列が入っていた場合は、ANSI換算のバイト区切りで、ユーザー定義体のメンバーに正しく読み込まれる。

Type Record   
    ADD As String * 8
    Name As String * 8
End Type

ファイル内容 あいう@@12345678   
上記を読み込むと
ADD = あいう@@...
Name = 12345678

と正しく読み込まれる。
書き込みも、逆に行われるだけで、正しくセットされる。
put/getは改行の概念がない。openするときのlengthが単位となる。
汎用機と同様な改行を付加する場合は、書き込むときにchr$(13)+ chr$(10)=CRLFを最後にデータの一部としてセットする必要がある。
エディター等でこのファイルにパッチを当てるとき、エディターの種類によっては改行コードをCRLFまたはCRのどちらか不定のことがあるので注意する必要がある。

ファイルのIOの方法2種

VBには、ファイルのアクセス方法として良く使用するものが2通りある。一つは改行記号までを1レコードとしてあつかう、可変長に向くタイプ。もうひとつは、構造体を利用して読み込むタイプであり、漢字・ANKが混在しても位置がづれない。1997/10/22

固定長タイプ

Open "MotoFile" For Random As 1 Len = 256
Open "SakiFile" For Random As 2 Len = 256
'レコード数を調べる
RecordCount=LOF(1) \ 256
'読み込み
Get #1, Index , usr_IO_Rec
GETしたあと、読み込めなかった時は、EOF()がTrueになる
'書き込み
Put #2, Index, usr_IO_Rec
Close

INDEXは、1スタート

可変長タイプ

Open "MotoFile" For Input As 1
Open "SakiFile" For Output As 2
'読み込み
Line Input #1, str_IO
Line Inputしたあと、最後の有効レコードの時、EOF()がTrueになる
'書き込み
Print #2, str_IO
Close


0002    コンボボックスでIMEMODEプロパティーを使用するときの注意。

デザイン時のプロパティーでIMEMODEを設定しても、gotFoucusイベントにより、勝手に変更されてしまう。これを防ぐために下記のように強制的にをIMEMODEをセットするしかない。

comboobject.imemode = vbIMEDisable    (使用禁止にする)


0003    クラスモジュールの要点


0004    Single型は、恐くて使えない。

Dim wk_single as single
wk_single = 3.1
debug.print wk_single

これを見ると、3.100001234などのゴミが残っている。これを計算にそのまま使うと、誤差が出る。Single型は使用しないほうが懸命であり、Double型で代用すべきである。

インデックスの0004も参照。


0005    コマンドボタンの不思議なバグ。

コマンドボタンをVisble Falseにした後で、なぜかコントロールBOXがアクティブになってしまった。
(草川担当 一覧表画面にて。対応策は、フォームのコントロールBOXをFalseにした。)


0006    計算の精度

integerどうしのかけわりの結果で、小数点付きの場合でも、答えはSingle型相当の制度しかでない。より正確に計算したい場合は、キャストする必要がある。


0007    INIファイルの制限

INIファイルの大きさは、64Kbyteまでである。それ以上は、APIで読み込めない。 97/05/31


0008    Val関数

Val関数の戻り値は、どんな時でも必ず数値を返す。(Null値はNullを返す)ただし、カンマ、ブランク、数字以外の文字が入っているときは、その直前までしか返さない。


0009    Fix関数の謎。

ごくまれに、小数を含まない数値(doubleでも)をFixすると、値が狂う時がある。原因不明。

→浮動小数点をfixするとなるケースがある。single型の3は2.99999.......かもしなないから。


0010    関数の引数の制限。

ユーザー定義型を、関数の引数に使用するとき、BYREFは使用できない!。

動的配列を引数に使用することは可能である。

dim aaa() as integer
Call subroutine(aaa)

97/10/13


0011    ユーザー定義型とFRMモジュールの制限

FrmモジュールにPublicの関数を宣言するとき、その引数にはPublicのユーザー定義型を使用することができない。コンパイルエラーになる。
(VB4)

FrmモジュールにPublicの関数は、ダメだけど、
Friendの関数にすれば、okだった!

(VB6 2003/01/17)


0012    ダイアログフォーム

フォームをモーダル表示すべく、Show 1 を使用した場合、ダイアログがアンロードされるか、非表示されるまで、次のstepに進まない。


マイクロソフトの思想を想像すると、タスクバーには、アプリケーションの種類を表示するものと思われる。であるから、SDKを見てもツールウィンドーはダイアログフォームはタスクバーには表示しずらいもののようだ。実際、ShowinTaskBar=Trueにしても Show vbModalにすると、タスクバーには出せない。

アプリケーションの作りは、メインフォームだけは、モードレスフォームにするのが正しいロジックなのかもしれない。

http://www.mtakahashi.com/old/a4625.html
http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_TaskTray.html

2002/02/26


0013    項目移動をエンターkeyで行うGUIを設計するときの注意。

Keydownイベントで、Send{"TAB"}を使用するのが一番簡単だが、漢字入力のテキストボックスのためにIME ModeをONにしようとしても、Send{"TAB"}を使用した場合うまくいかないことがあった。
原因不明。解決方法はSetFocusしかない。


0014    VBから印刷を行う時に、EXCELを使用する上での注意。

VBAによるOLE通信機能を使用すれば、VBでEXCELをフルコントロール可能である。
しかし、doeventsを適宜入れないと、VB側の処理がうまく行われないときがあった。
OLEによるプロセス間通信は、遅くて耐えられない。早い順に、VB内部コード>EXCEL内部マクロ>OLE通信 の順である。VBとEXCELの間の通信は極力避けたほうが良い。


0015    隣接するテキストボックスA、Bで、Aの入力内容により、Bを入力可、不可に切り替える方法

通常はロストフォーカスで、BのEnabled Falseを行うが、隣接している場合はこの方法がつかえない。TABを押した時点でBにフォーカスが移動しているからである。よって下記の方法をとる。

A.Cheng events
    if A.text = NG then
        B.tabstop = false
    else
        B.tabstop = true
        B.enabled = true
    endif

A.lostfocus events
    if A.text = NG then
        B.text = ""
        B.enabled = false
    else
        B.enabled = true
    endif


0016    [ALT]+[TAB]で表示される候補

windowsで[ALT]+[TAB]で表示される候補は、タスクバーに並んでいるものである。その表示名は、フォームのキャプションである。
タスクリストに表示されるものも、タスクバーに並んでいるものである。


0017    あるフォーム(A)から、ダイアログフォーム(B)を表示。この時(A)上のマウスポインターを砂時計にし、(B)上のマウスポインターは既定値にする方法。

  1. (B)をインプロセスOLEサーバー形式にて実装する。
  2. (A)でScreen.Mousepointerを操作する。
  3. (B)のScreen.Mousepointerは(A)と別に制御できる。

0018    SSパネルでフォーカスを持つと、IMEが制御不能になる。

SSパネルをクリックすると、フォーカスがSSパネルに移る。しかしGOTフォーカスイベントは存在しない。IMEのON・OFFを制御するフォームに於いて、パネルをクリックすると、パネルがフォーカスを持っている間、IMEモードはwindows依存になる。勝手にONになることもあるので注意。
API関数を使用してフォームのhWNDをもとにIMEOFFにする方法が有るかもしれない。 97/08/19


0019    MultiLine Trueのテキストボックスの制限

上記のテキストボックスでkeyDownイベントを使用する場合、下記のキーは正しく制御できない。
とりあえず、発見したもの。

97/08/20


0020    dir関数の制限

この関数は、初回に引数をセットし、2回目に引数なしでCALLすると次々とファイル名が取得できるが、その間に下位関数等でDir関数を使用していると期待どうりの動きをしない。loopのなかのloopも使用できないので注意。   
97/10/13


0021    LSet関数の制限

ユーザー定義型どうしの転送に良く使うが、下記の構造のユーザー定義型はLSETできず、コンパイルエラーになる。

Type t_a
    k1 as string *1
end Type

Type t_b
    k1 as t_a
end Type

Type t_c
    k1 as t_a
end Type

dim b as t_b
dim c as t_c

Lset c = b

ユーザー定義型の配列を持つユーザー定義型は使用できない
97/11/04

ユーザー定義型の配列を持つユーザー定義型についての、解決方法発見。
lsetでは無理であるが、API関数CopyMemoryを使用すれば、簡単に実現できる。1999/08/03


0022    App.Pathの定義

カレントディレクトリではなく、当EXEファイルの存在ディレクトリが取得できる。
97/11/07


0023    Shell起動した画面フォームがアクティブにならない?

起動元EXEで、起動先EXEを起動した後、起動元EXEのロジックでSETFOCUSを行うと起動元フォームがアクティブになってしまう。起動元のSETFOCUSが先に走り、後で起動先の画面がSHOWされればこの現象は起きない。しかしタイミングの問題で保証性がない。
不完全な回避方法は、起動先EXEのフォームロードイベントの最後に、DOEVENTSを行うことにより、起動元のSETFOCUSを完了させてしまう事である。
98/01/28


0024    相対パス指定時の注意

shell 関数などで起動exeを相対パスで指定する時に、自分のフォルダーを基準に考えると、うまくいかないことがある。原因は、相対パスはあくまでカレントパスの相対だからである。自分のフォルダー(app.path)は、必ずカレントパスになっている保証はない。
完全な解決方法はapp.path & "\" & [相対パス]で指定することである。事実上絶対パス指定になる。
98/04/15


0025    OLE(ACTIVE X)

インプロセスOLEサーバーの作り方

  1. 標準モジュールを定義する。(推奨)
  2. クラスモジュールを最低一つ定義する。(必須)
  3. インスタンスは"2"にする。
  4. パブリックにする。
  5. クラスモジュールに宣言したPublicファンクションまたはサブがそのクラスのメソッドになる。
  6. オプション-プロジェクト-プロジェクト名を宣言する。これは、クライアントからの識別子になる名前である。しかもパソコンの中でユニークな名前にする必要がある。
  7. オプション-プロジェクト-アプリケーションの説明を宣言する。これは"参照設定で選択するときの説明文"になる。
  8. ファイル-OLE DLLの作成を行う。
  9. クライアント側は、参照設定でdllをチェックする。

クラインと側の呼び出し例

Dim 項目As New 識別子.クラス名
call 項目.メソッド名

インプロセスOLEサーバーのモーダルフォームについての補足。

インプロセスOLEサーバー内でフォームを表示するときは、モーダルフォームしか使用できない。(仕様)
VBPでテスト中は、クライアントに対して別のVBのプロセス、つまりアウトプロセスで動いているので必ずしもクライアントに対してモーダルにならない。が、DLLにしてからはクライアントに対してモーダル表示になる。
インプロセスOLEサーバー(a)から、インプロセスOLEサーバー(b)の呼び出しは可能である。このとき、(a)のクライアントは、(b)を参照設定しておく必要がない。


0026    インストール ウィザード(ver 4.0) 配布ファイルを手動で追加する時に相対ディレクトリを指定する方法。

ディフォルトは、EXEと同じディレクトリになっている。
$(AppPath)
たとえば、<EXEDIR>\DATA\に入れたい時は、
$(AppPath)\DATA
と指定すれば良い。
1997/10/24


0027    レジストリ登録について

以下の方法で、手動でdll / ocxを登録できる。       REGSVR32.EXE XXXX.DLL
削除の方法は                                                 REGSVR32.EXE /u XXXX.DLL


0028    DDEのTOPICに何を編集するか

VBどうしでDDEの通信をするときの方法。
〜.LinkTopic = 相手のApp.Title | 相手のLinkTopic である。


0029    長い名前のVBPファイルをopenすると、短い名前に変化されてしまう。

対策方法
エクスプローラなどから、ファイルの関連づけを変更する。
"c:\program files \DevStdio\vb\vb5.exe" "%1"
のように、EXE名を"で囲む。 1998/06/08


0030    BEEPがならないとき

コーディング上で、BEEPと記述してたときの音は、コントロールパネルのサウンドの"一般の警告音"に設定されている音が鳴る。
サウンドドライバーがインストールされていないマシンでは、自動的に本体のBEEP音がなるが、サウンドドライバーがインストールされているマシンでは、注意。1997/12/07


0031    App.Exenameの注意

エクスプローラー上の名前が"TestExe.exe"であっても、SHELL "TESTEXE.EXE"とした場合、App.Exenameは"TESTEXE"になる。
1998/05/12


0032    よく使用するonerrコード

1998/12/25


0033     処理中にボタンクリックイベントを無効にするときの問題点

一般に、Enabled=Falseのコントロールは、クリックイベントを受け付けないが、Enabled=Falseにしたイベント処理が終わっていないときは、イベントを受け付けてしまう。完全に防ぐためには例えばスクリーンオブジェクトのマウスカーソルイベントが砂時計のときは、クリックイベントを抜けるような対策を練る事である。
1998/12/27 


0034    For Eachを利用したフォーム上のコントロールの初期化

Dim L_Control As Control 'フォーム上のコントロール操作に使用

'**** 各種コントロールを初期化する
For Each L_Control In Me

Select Case TypeName(L_Control)

Case "TextBox", "ImText"
'コントロールのテキストをブランククリアする。
'バックカラーをノーマルに戻す
L_Control.Text = ""
L_Control.BackColor = CC_ColorBack

Case "ImDate"
'日付コントロールのテキストを初期化する。
'バックカラーをノーマルに戻す
L_Control.Number = 0
L_Control.BackColor = CC_ColorBack

End Select
Next L_Control


0035    NULLについて

VBには、いくつかのNULLに関する定数がある。それぞれ以下のような意味である。

1999/07/05 山口の自習より


0036     タブダイアログコントロールのバグについて

VBに標準でついている、タブダイアログコントロール(SSTAB)上にフレームを置いたとき、LOADイベント中でENDしてもうまくいかない。ENDせず不安定な状態で処理が続行できてしまう。
1999/07/29 


0037    VisualBasicから裏でAccessを制御するときの制限

CreatObjegt を行い、 Object.Visible = false とすれば、ExcelやWordは全く見えなくなるが、Accessはタスクバーにアイコンがみえてしまう。マイクロソフトによれば、これは仕様との事。
Office97 98/03/04


0038    誤差について

厳密な計算を要求される金額計算などのロジックを使う時は、ご一読。

マイクロソフトサポート技術情報 [VB4] データ型と演算誤差についての注意 : J029974

1999/09/21


0039    メニューバーのあるフォームの初期表示位置

メニューバーのあるフォームの初期表示位置は、StarupPositionの設定ができない。
よって、Loadイベントなどで、コーディングする必要がある。

例)
Me.Left = (Screen.Width - Me.Width) / 2
Me.Top = (Screen.Height - Me.Height) / 2

1999/09/21 


0040    開発環境で実行中の無限ループより、復帰するには

[Ctrl] + [Break] で、止まります。

1999/11/25 B.O.C. より


0041    半角文字と全角文字てピッチを揃えたいときに

テキストボックスなどを上下に配置したときにピッチ(桁位置)を揃えるためには、次のフォントを使用のこと。

MSゴシック/MS明朝 9ポ or 12ポ (これ以外の大きさでは揃いません)
Terminal
System

2000/04/15 伊東君の投稿を元にしました。

2003/10/29 時点では、揃っている!WindowsXPでは、揃うように改善されているのか......?

↑WindowsXPではフォントピッチの扱いが変更されています。
MSDN :Windows XP での全角固定ピッチフォントの仕様変更  を参照
2004/05/21


0042    ユーザーイベントの実装例

自分で作ったクラスには、ユーザーイベントを実装することができる。VB5〜 それの実装例をしめす

Project1.vbp

form1を作成し、コマンドボタンCommand1と、テキストボックスText1を配置。
以下のコードを貼り付ける。


        
'Class1を、イベント付きクラス名として、clsTestを定義
Dim WithEvents clsTest As Class1


Private Sub clsTest_eventCommand1()
	Text1.Text = "eventCommand1"
End Sub

Private Sub clsTest_eventCommand2()
	Text1.Text = "eventCommand2"
End Sub


Private Sub clsTest_eventStarted(starttime As Date)
	Text1.Text = "eventStarted " & Format(starttime, "hh:mm:ss")
End Sub


Private Sub Command1_Click()
	Set clsTest = New Class1
	clsTest.main
End Sub
        
        
        

インベント付きのクラスを作成する。

ライブラリー名:cClass1  (プロジェクトのオブジェクト名に相当)

クラス名:Class1

'クラスの外部公開用のユーザーイベントの宣言
Public Event eventStarted(starttime As Date)
Public Event eventCommand1()
Public Event eventCommand2()




Public Sub main()
    
    'クラスの利用者に対して、スタートされた事を通知する
    RaiseEvent eventStarted(Now)

    
    'form1に対して、クラスのメソッドを呼び出すことが
    'できるように、自分自身のインスタンスを与える
    'C++のthis pinter を渡すのと同じ意味
    
    Set Form1.cClass1 = Me
    
    Form1.Show
    
End Sub


'
'Friendは、このプロジェクト内でのみ有効なスコープ
'インスタンスの利用者からは見えない
'
Friend Sub subCommand1()
    
    'イベントを発生させる
    'RaiseEventは、クラスモジュールでしか、使えないようだ
    RaiseEvent eventCommand1

End Sub
'
'Friendは、このプロジェクト内でのみ有効なスコープ
'インスタンスの利用者からは見えない
'
Friend Sub subCommand2()
    
    'イベントを発生させる
    RaiseEvent eventCommand2
    
End Sub

 form1を作成し、コマンドボタンCommand1とCommand2を配置。
以下のコードを貼り付ける。

        
Private Sub Command1_Click()

    'クラスのインスタンスのメソッドを呼び出す
    Call cClass1.subCommand1
    
    '本来なら
    'RaiseEvent cClass1.eventCommand1
    'のように直接イベントを呼び出したいが、
    'できなかったので、メソッド経由にした。
    
End Sub


Private Sub Command2_Click()
    
    'クラスのインスタンスのメソッドを呼び出す
    Call cClass1.subCommand2

End Sub

        
        

クラス側では、クラスモジュール以外では、RaiseEvent を呼び出せないので注意。上記の例では、クラスへのポインタ変数を利用したメソッド呼出を行い、その中で、RaiseEventを使用している。

2001/06/25


こんなメッセージが出た

ID 文字列が長すぎます: '項目'
ActiveX コンポーネントの ProgID は、39 文字以内の文字列でなければなりません。ProgID は、プロジェクト名とクラス モジュール名を連結して作成されます

命名時には注意ですねー

2003/05/02

0043    フォームにエクセルを貼り付ける基本

  1. ツールウィンドーよりOLEコンテナを選択

  2. 貼り付け先のフォームで範囲を矩形選択すると、

    Excelを選択。
  3. 後は、オブジェクトを右クリックして、編集などすればOK。

2002/07/09


0044    フォームオブジェクトについての考察

フォーム単純にshowすると、まるでコンスタントオブジェクトのごとく振る舞う。つまり
 クラス名.メソッド
の動きになる。よってフォームの名前(VBで言うところのオブジェクト名)さえ分かっていればアプリケーションのどこからでもアクセスする事が可能になる。
また、アプリケーション内で必ず1つしか実体が存在しない事が保証できる。

一方クラスとインスタンスを完全に分ける実装も可能である。


    Dim form1 As Form
    Set form1 = New frmSpotKensyouMain
    form1.Show

これは、インスタンスを幾つも作ることが可能になるので、同一種類のフォームを幾つも表示する事が可能になる。

フォームのInitializeイベントは、インスタンスを生成した時に発生するとヘルプにある。
Set〜New を行ってフォームをハンドリングした場合は、期待通りのイベントが発生するが、
スタティクで運用した場合は、一番最初に呼び出した時だけ発生する。
ただし
  Set クラス名 = Nothing
とすれば、スタティックといえども、破棄されると思われる。(再度呼び出すとInitializeイベントが発生するこから)

「クラス名.メソッド」で運用する場合、Initializeイベントでコントロールの初期化を行なう場合は要注意。
アンロードすると、フォーム上のコントロールの値は消えてしまう。再度ロードを行った時は、デザイン時のプロパティで初期化されている。
VBの設計思想がよく判らないが、クラス単位にフォームインスタンスを保持できるポインタがある雰囲気かもしれない。Initializeイベントはそのポインタに実体をアロケートした時のCALLBACK関数と考えれば、合点がいく。

参考資料
マイクロソフト サポート技術情報 - JP147665
http://support.microsoft.com/default.aspx
http://www.microsoft.com/japan/support/kb/articles/JP147/6/65.asp

2002/07/17

大変参考になる記事を見つけた
http://www.gj.il24.net/~nakasima/vb/tech/end/index.htm
2002/07/31

 


0045    テンプレート

C:\Program Files\Microsoft Visual Studio\VB98\Template配下の各フォルダに自分で作ったやつを放り込んでおくだけで、新規作成ダイアログの中にも登場させる事ができるようになります。

けど、テンプレートを修正したからといって、既存のものが修正されるわけでもなく、あんまり有効利用が出来そうにないようにも思えます。

2002/07/22


0046    IDEのショートカット

ちょと使ってないと、すぐ忘れるんですね〜。
けど、ほとんど、メニューバーに説明が乗っていますから、それを見ながら思い出しましょう。

ショートカットキー 内容  
Ctrl + R プロジェクトウィンドウを表示  
Ctrl + Shift + F2 コードの元の位置に移動することができます。コードを編集しているか、[プロシージャの定義] コマンド呼び出しを行っていて、コード ウィンドウが表示されているときのみ有効です。最後にアクセスされた行または編集された行が 8 つまで、記録されています。デザイン時 および中断モードでのみ使用できます。  
F8 いきなりステップ実行  
Ctrl + Break 実行処理の強制停止  

2002/08/28


0047 VBのメモリー管理って、ガベージコレクション

自分でNewしたインスタンス変数に Set Nothing しても、インスタンス変数そのものはnullになるけど、実体は生き続けている時がある。他の変数が、実体を保持している時だ。

Javaと同様、どこからも参照されなくなった時点で、消滅するみたい。


    Dim wk  As Class1
    Dim kp1 As Class1
    
    
    Set wk = New Class1     'ここでアロケートされる
    
    Set kp1 = wk            '参照をコピー
    
    Set wk = Nothing        'wkはnullになる
    
    Me.Print kp1.Property   '動く

    Set kp1 = Nothing       'ここで、消滅する

注意点は、VBのガベージコレクションは、参照する変数が無くなった時点で必ずスグ解放する事らしい。

.NETのVBでは、JAVAと同じく、解放タイミングは不定だそうです。

http://www.microsoft.com/japan/msdn/net/vbtransitionguide/chapter2/chapter2_5.asp

2002/08/09 


0048 オプションボタンのグループ化ってどうやるか?

変数名だけでは、できません。
フレーム、イメージボックスなど、コンテナに載せないとできません。

VB6 2002/09/11


0049 隠し関数のメモ

文字列変数のアドレス取得関数
StrPtr()

データ型変数のアドレス取得関数
VarPtr()

オブジェクト変数のアドレス取得関数
ObjPtr()

2002/10/08


0050 VBの配列はCとは内部構造が違うぞ!

Visual Basicの配列の実体はSAFEARRAYであり、次元や要素数とデータを指すポインタのフィールドを持つ構造体である。
http://www.ops.dti.ne.jp/~allergy/com/com.html

 

オートメーションを使って配列を渡すには、セーフ配列(へのポインタ)を含むバリアントを作成します。セーフ配列は単一のデータ型の一次元または二次元の配列です(しかしこの単一データ型は VARIANT でもよいため、型を複数含んだ配列も可能です)。Visual Basic では配列の下限は 0 でなくてもよいので、セーフ配列には下限とサイズも格納しなければなりません。

これらの配列がセーフ配列と呼ばれるのは、これらが範囲情報持ち、配列のデータにアクセスする前に添え字の範囲を確認できるからです(SafeArrayGetElement SafeArrayPutElement API はこれを自動的に行います)。これに比べ、C と C++ 配列の範囲検査が行われることはめったにないため、添え字の有効範囲を超えたことによる原因究明の難しい大きなエラーが起きやすいのです。
http://www.microsoft.com/japan/developer/library/dsmsdn/drgui042099.htm

2002/10/09


0051 コントロールを動的に増やして配置する

オプションボタンやコマンドボタンなど、フォーム上のコントロールを動的に増やすには LOAD命令を使えばできる。ただし、増やす元になるクラスが配列コントロールとして存在していないとダメ。


For ix = 1 To 3
    
    ’コマンドボタンインスタンスを生成する
    Load cmdArray(ix)

    ’縦に並べる
    cmdArray(ix).Top = cmdArray(ix).Top + ix * 300
    
    '可視状態に変更する
    cmdArray(ix).Visible = True
    
Next ix

これを応用すると、メニューバーの項目も動的に追加することができる。


For ix = 1 To 10
    
    Load men_array(ix)
    men_array(ix).Caption = "メニュー項目" & ix

Next ix

ということは、減らす時は、Unloadすれば良いわけですね。

http://www.ag.wakwak.com/~kagawa/vbtipmenu.htm

2002/10/24


0052 クラスのメソッドは、スタティックメソッドは実装できるのか?

できん。

NEW してからでないと、クラスは使えないみたい。

2002/11/12


0053 強制リブートの考察

強制リブートやシャットダウンを行なう際、起動中のプロセスがあると、落とせないことがある。それを可能にするための手法についての考察を行なう。

詳細

2002/11/13


0054 Collection型には、ユーザー定義型は入らないのか?

ヘルプには、

コレクション、オブジェクト、またはユーザー定義型を構成する要素。

と書いてあるが、実際は入らないジャン。オブジェクトしか入れれないよ〜

2003/01/29


0055 フォームからアイコンを消す方法

方法1 アイコンプロパティを「BS」ボタンなどで、(なし)にする。

方法2 Me.Icon = Nothing      Set文をつけないことがポイント

2003/04/09


0056 ON ERRORの内容が消えてしまう?

以下の手順で実装したとき、不具合が発生した

  1. On Error の宣言
  2. API系のメソッド(CreateProcess)をCALLし、失敗
  3. 戻り値が正常以外なので、ERR RISE
  4. エラーハンドラーにて、MsgBox"エラー発生" を表示
  5. エラーナンバーや、エラーディスクリプションを見ると、クリアされている。

つまり、エラーの内容が消えてしまったという話。
やっかいな事に、IED環境で動作検証すると、エラーナンバーなどは消えていないのです。

予想として、エラーナンバーが消えたのは、MsgBoxが内部でAPI関数をCALLし、その結果は正常復帰しているので、エラーナンバーが消えたのでしょうか...

このケースの対応方法としては、エラーナンバーなどの情報は、ハンドラーの頭で退避する等の考慮が必要という事で処理しました。

「IDEだと発生しない」に関しては、IED側がデバッグのアタッチをする時に、特別なシカケを持ち込んでいるのかもしれませんねぇ〜。

2003/07/04


0057 DLLが見つからない! エラー53

ただしくパスを切ったハズのDLLが見つからないとき、そのDLLが内部で読んでいるDLLが見つけられない時にも、53が表示される。

紛らわしい〜

2003/07/04

更に、DEFファイルを使われていないDLLの場合は、名前が見つけられなくて、「ない」って言っているかもしれない。
やっぱりVBから呼ばれるDLLは、__stadcall が必須で defファイルで名前を修飾しておかないとあかんですね〜

2003/07/14


0058 フォームのアイコンのメンテナンスを簡単に行うには

そこで、
ダミーのフォームを作成し、そこにアイコンを設計時に取りこんでおく。実行時、frmA.icon = frmB.icon で、アイコンの取得及び複写ができる。これを関数化すれば良い。

つまり、frmBのアイコンさえ取込なおせば、あとは全てアイコンが切り替わる事になる。無論、実行環境には、アイコンファイルは不要である。

注意事項はfrmBからアイコンを取得した時に、frmBのインスタンスが生成されてしまうので、Unloadする事を忘れずに行なうこと。

ベストな方法ではないけど、運用面を考えれば検討の価値ありかも

2003.07.31


0059 VBではGetLastErrorは使えない

詳細エラーコードを取得したい時は、Err.LastDllError を使用すること。

2003/08/11


0060 VB6でも、WindowsXP Lookは実現できる

exeと同じフォルダに、exe名.manifestを配置すればよい。

これは、.NETアプリケーションだけ有効になるものでもなく、WindowsXP自体が、XMLファイルによりLook&Feelを指定できる機能を保有しているからである。

VB6.EXE.manifest


<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly 
	xmlns="urn:schemas-microsoft-com:asm.v1" 
manifestVersion="1.0">
<assemblyIdentity 
	processorArchitecture="x86" 
	version="1.0.0.0"
	type="win32"
	name="VB6.EXE"/>
	<description></description>
	<dependency>
	<dependentAssembly>
	<assemblyIdentity
		type="win32"
		name="Microsoft.Windows.Common-Controls"
		version="6.0.0.0"
		publicKeyToken="6595b64144ccf1df"
		language="*"
	processorArchitecture="x86"/>
	</dependentAssembly>
	</dependency>
</assembly>

これはVB6のIDEに対して設定したものである。すると、IED内で開発中のものまで、対応してくれる。

注意事項

VB6で作成したアプリケーションに、この技を適用する場合、以下の不具合が見受けられる。

フレーム内に配置した、コマンドボタンの枠が異様に太い、オプションボタンの背景色が真っ黒

フレーム内の不具合については、MSDNでも認めているようである。コマンドボタンなどをイメージリストコンテナに格納し、それをフレームに格納すれば表面上回避できる。

あとMicrosoft Common Controls 6.0 SP4 はLookが変更されない。
Microsoft Common Controls 5.0 SP2 は、変更が有効になるようだ。

manifestファイルは、リソースファイルとしてexe内に組み込みが可能であり、配布がスマートになる。が、VB用のリソースエディタ、VC++エディタでも、うまくいかなかったとネットにあったようだ

補足情報

Look&Feelを特に意識していないアプリケーションは、中途半端にlookが変更される。
フォームのヘッダや、スクロールバーなどがその例である。

exeのプロパティから「視覚テーマを無効にする」をチェックすれば
無効になるようである。

2003/09/05


0061 スクリーンセーバー動作中に、メッセージボックス?

  パスワード設定無しのスクリーンセーバー パスワード設定有りのスクリーンセーバー
通常のメッセージボックス メッセージボックスが表示されるが、スクリーンセーバーは解除されない。 メッセージボックスが表示されるが、スクリーンセーバーは解除されない。
システムモーダルのメッセージボックス スクリーンセーバーが解除されて、メッセージボックスが表示される。 メッセージボックスが表示されるが、スクリーンセーバーは解除されない。

2003/09/10


0062 シェルコマンドをプログラムから起動する方法


Shell "command.com /c test.bat", vbHide

/c は実行環境後、復帰するスイッチ
vbHide をつけると、DOS窓が画面上に表示されなくなる。

2003/10/02


0063 EXE分割されても、親よりも必ず手前に表示されるモーダレスダイアログのように振る舞うフォームの実装方法

通常、上記の要件を実装する場合は、同一EXE内で、下記のように実装する


frmKodomo.Show vbModeless, frmOya

こうすれば、frmKodomo のオーナーがfrmOya となり、frmOyaを最小化した時にも、frmKodomoも最小化され、美しい動きとなる。

しかし、frmKodomo と frmOya を異なるexeとして実装したい場合は、以下の方法で実装できる。

親側


Dim lngMeHandle As Long
Dim strMeHandle As String

Dim strShellString As String

lngMeHandle = Me.hWnd
strMeHandle = CStr(lngMeHandle)
strShellString = "ko.exe " + strMeHandle

Shell strShellString, vbNormalFocus

子供側



Option Explicit

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Const GWL_HWNDPARENT = (-8)

Private Sub Form_Load()

    Dim strParameter    As String
    Dim lngHandleParent As Long
    
    strParameter = Command$
    
    If strParameter <> "" Then
        lngHandleParent = CLng(strParameter)
        Call SetWindowLong(Me.hwnd, GWL_HWNDPARENT, lngHandleParent)
    End If

End Sub


Private Sub Form_Unload(Cancel As Integer)
    
    Call SetWindowLong(Me.hwnd, GWL_HWNDPARENT, 0)

End Sub

解説

子供側で、SetWindowLongを使用し、Windowスタイルを変更する。変更内容は、親を変更する事である。親フォームのハンドルが必要となるが、この例では、文字列化する事により、起動引数として取得している。

なお、アンロードイベント時に、親ハンドルをクリアしているのは、親子関係を解消しておかないと、子供の終了時に落ちるという噂があったので、入れてある。

http://www.snark.co.jp/soft/faq/VB_A2.HTM#Q15

 2003/10/27


0064 コマンドライン引数の制限はどのくらいか?

単純に実験したところ、32757文字までだった。それ以上の文字を与えた場合は、無視された。

ところで、String型の説明を読むと

文字列型 (String) には、約 63KB までの長さの固定長文字列、約 2GB (20 億文字) までの可変長文字列を格納できます。

とあるので、固定文字列長の制限に影響されているかもしれませんねー

 2003/11/07


0065 四捨五入と丸め

Format関数は、四捨五入
代入は、丸め

3 = Format(2.5,"0")

2 = CLng(2.5)

[VB4] データ型と演算誤差についての注意 2004/01/28


0066 VBでも継承ができる?

Implements ClassName 継承ができるとヘルプには、書いてあったが、継承元クラスのメソッドを全てオーバーライズしなければならない。つまり、この機能は、インターフェイスの継承に有用である。

ちなみに、フォームオブジェクトでもImplementsを使用することにより、インターフェイスを用い簡易ポリフォーイズムを実装することができるみたいだー。

2004/01/30


0067 タブコントロールの不思議

TABSplitは、マウスダウンの直後に選択タブが切り替わる

表示要素を切り替える為にクリックイベントをトリガーにすると、TABSplit上でマウスアップに効かないと、クリックが発生しないのでタブだけ変わって、表示要素が切り替わらないという減少が発生することがある。

ならば、SSTABにすると良いのだが、たまたまあるプロジェクトでキャプションを太字に指定すると、アクティブなタブだけが、通常文字に切り替わってしまった

結論
TABSplitを採用
イベントは、マウスダウンでタイマーイベント経由で表示要素を切り替えた

2004/02/04


0068 メッセージボックスが2つでるケース

普通、メッセージボックスが出ている時は、他の処理はできないものである。よって、メッセージボックスが2つ出ることは無いと感じられる。それは、マルチスレッドでは無いから〜。

しかし、メッセージボックスで応答待ちになっている時に、タイマーイベントに起因するロジックは、走るようである。


Private Sub Command1_Click()
    MsgBox "Command1_Click"
End Sub

Private Sub Timer1_Timer()
    MsgBox "Timer1_Timer"
End Sub

ただしEXEにしてからでないと、再現できない。IDE配下だと再現できない。

2004/02/26


0069 画面サイズとディスプレーのサイズ

IDEを起動しているディスプレーの論理サイズより、大きいサイズのフォームはデザインできないようである。
フォームレイアウトでも、下記図よりも大きいサイズは作成できなかった

こまったこまった。

さらに、大きな解像度で保存したプロジェクトを、小さいサイズのPCで、フォームリソースを開かずしてコンパイルした場合も画面サイズに縮小されてしまうようだ!

でかいテレビ購入する理由になるねー

2004/03/02


0070 void型のDLLをVBから呼び出す時の型は?

APIビュアーを参照すると、void型の関数は、sub として宣言されているようでした。

2004/04/19




戻る