Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
long型のNull判定
投稿日時: 20/09/06 15:30:50
投稿者: BlackPanda

クリップボードのテキストデータを取得しようと思い、調べて行き着いた記事がAccess用だったのですがそれをExcel VBAに流用することにしました。
コードを見ていると気になる点があり、
それはAPIからの戻り値をLong型で宣言した変数に入れ、それをIsNullで確認しています。
これは正しく処理できるのでしょうか?
APIの戻り値がNULLだった場合はキャストされて0が代入されたりするのでしょうか?
APIまわりの知識が無く、もし参考になるサイト等ありましたら教えていただきたいです。
 
該当記事
https://www.moug.net/tech/acvba/0020003.html
https://docs.microsoft.com/ja-jp/office/vba/access/concepts/windows-api/retrieve-information-from-the-clipboard
 
該当プログラムの転載

    'Win32API宣言部
    Declare Function OpenClipboard Lib "User32" (ByVal hwnd As Long _
                                                ) As Long
    Declare Function CloseClipboard Lib "User32" () As Long
    Declare Function GetClipBoardData Lib "User32" _
                                          Alias "GetClipboardData" _
                                          (ByVal wFormat As Long _
                                         ) As Long
    Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags&, _
                                                 ByVal dwBytes As Long _
                                               ) As Long
    Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long _
                                              ) As Long
    
    Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long _
                                                ) As Long
    
    Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long _
                                              ) As Long
    
    Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _
                                             ByVal lpString2 As Any _
                                            ) As Long
    'パブリック定数
    Public Const GHND = &H42
    Public Const CF_TEXT = 1
    Public Const MAXSIZE = 4096

Function GetClipBoard()
    Dim hClipMemory  As Long
    Dim lpClipMemory As Long
    Dim MyString     As String
    Dim RetVal       As Long

    'クリップボードの状態チェック
    If OpenClipboard(0&) = 0 Then
        MsgBox "クリップボードを開けませんでした"
        Exit Function
    End If

    ' テキストを参照しているハンドルをグローバルメモリに取得
    hClipMemory = GetClipboardData(CF_TEXT)
    If IsNull(hClipMemory) Then
        MsgBox "メモリが割り当てられません"
        GoTo OutOfHere
    End If

    ' メモリをロックして、実際のデータ文字列を参照できるようにする
    lpClipMemory = GlobalLock(hClipMemory)

    If Not IsNull(lpClipMemory) Then
        MyString = Space$(MAXSIZE)
        RetVal = lstrcpy(MyString, lpClipMemory)
        RetVal = GlobalUnlock(hClipMemory)

        '終端Null文字を取り除く
        MyString = Mid(MyString, 1, InStr(1, MyString, Chr$(0), 0) - 1)
    Else
        MsgBox "メモリの確保に失敗しました"
    End If

OutOfHere:
    RetVal = CloseClipboard()
    GetClipBoard = MyString
End Function

回答
投稿日時: 20/09/06 21:18:55
投稿者: よろずや

困ったもんですねぇ。
 
https://docs.microsoft.com/en-us/windows/win32/dataxchg/using-the-clipboard

これをVBに翻訳するときに
if (hglb != NULL)
を勘違いしたんでしょうねぇ。
 
M$のサイトに書かれているからといって、まんまコピーするのもどうかと思いますけど。
 
Long型がNullになることはありません。

回答
投稿日時: 20/09/06 23:19:47
投稿者: WinArrow
投稿者のウェブサイトに移動

>これは正しく処理できるのでしょうか?
 
正しく・・・何をもって正しいと考えるのですか?
もし、エラーになるか/ならないか
といえば、エラーにはなりません。
 
あなたの意図と違うかもしれませんが、正しい処理です。
 
 
 
 

投稿日時: 20/09/07 00:33:55
投稿者: BlackPanda

よろずやさん
返信ありがとうございます。
> Long型がNullになることはありません。
やはりそうですよね。。。
APIがNullを返した時にLong型変数がどのようになるかわかりますでしょうか?
 
 
WinArrowさん
返信ありがとうございます。
> 正しく・・・何をもって正しいと考えるのですか?
「プログラムが意図したとおりの動作をする」
を正しく処理できると考えています。
 
今回の質問としては下記のコードが、
「APIが正常に処理が出来ずにNullを返した時にMsgBoxを表示する」
と意図しているが、IsNull(Long型変数)の記述でMsgBoxを
表示できるのかということです。

hClipMemory = GetClipboardData(CF_TEXT)
If IsNull(hClipMemory) Then
    MsgBox "メモリが割り当てられません"
    GoTo OutOfHere
End If

 
 

回答
投稿日時: 20/09/07 06:35:34
投稿者: WinArrow
投稿者のウェブサイトに移動

>「プログラムが意図したとおりの動作をする」
 
でも、あなたが意図したことをコードにしたのですから、
 
あり得ないことを想定したコードは、無駄というものです。
 
議論するだけ無駄

回答
投稿日時: 20/09/07 07:40:40
投稿者: たらのり

おはようございます
 
> APIがNullを返した時にLong型変数がどのようになるかわかりますでしょうか?
 
このとき、Long型の変数の値は 0 だと思います。
 
ですので、以下のようにすれば判定できると思います。
 

hClipMemory = GetClipboardData(CF_TEXT)
' If IsNull(hClipMemory) Then
If hClipMemory = 0 Then
    MsgBox "メモリが割り当てられません"
    GoTo OutOfHere
End If

投稿日時: 20/09/07 09:14:33
投稿者: BlackPanda

たらのりさん
返信ありがとうございます。
 
クリップボード関連のAPIを調べていたところ、
GlobalFreeが成功時にNullを返してくれることがわかったので下記のコードでテストしてみました。
その結果、Nullだった場合に0になることを確認できました。
たらのりさんに提示していただいたコードに改修して使用していきたいと思います。
 
ありがとうございました。
 

Sub test()
    Dim hGlobalMemory As Long
    Dim result As Long
    
    result = 1
    
    'グローバルメモリ確保
    hGlobalMemory = GlobalAlloc(GHND, 10)
    Debug.Print hGlobalMemory
    
    '確保したメモリの解放
    result = GlobalFree(hGlobalMemory)
    
    Debug.Print result
End Sub