Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


7251 / 13644 ツリー ←次へ | 前へ→

【40304】(Not WS_SYSMENU)ってどういう意味です... mutu 06/7/11(火) 10:18 質問[未読]
【40305】Re:(Not WS_SYSMENU)ってどういう意味で... Statis 06/7/11(火) 10:26 発言[未読]
【40306】Re:(Not WS_SYSMENU)ってどういう意味で... mutu 06/7/11(火) 10:35 質問[未読]
【40308】Re:(Not WS_SYSMENU)ってどういう意味で... Blue 06/7/11(火) 10:53 発言[未読]
【40310】Re:(Not WS_SYSMENU)ってどういう意味で... ひげくま 06/7/11(火) 11:02 発言[未読]
【40311】Re:(Not WS_SYSMENU)ってどういう意味で... ひげくま 06/7/11(火) 11:05 発言[未読]
【40309】Re:(Not WS_SYSMENU)ってどういう意味で... ichinose 06/7/11(火) 10:59 発言[未読]
【40314】Re:(Not WS_SYSMENU)ってどういう意味で... mutu 06/7/11(火) 12:36 お礼[未読]
【40316】SetWindowLongPtrを使うには? mutu 06/7/11(火) 13:47 質問[未読]
【40318】Re:SetWindowLongPtrを使うには? Blue 06/7/11(火) 14:00 発言[未読]
【40322】Re:SetWindowLongPtrを使うには? mutu 06/7/11(火) 15:16 質問[未読]
【40323】Re:SetWindowLongPtrを使うには? Blue 06/7/11(火) 15:22 発言[未読]
【40324】Re:SetWindowLongPtrを使うには? mutu 06/7/11(火) 16:23 お礼[未読]
【40325】Re:SetWindowLongPtrを使うには? Blue 06/7/11(火) 16:46 発言[未読]
【40330】Re:SetWindowLongPtrを使うには? mutu 06/7/11(火) 17:21 お礼[未読]

【40304】(Not WS_SYSMENU)ってどういう意味です...
質問  mutu  - 06/7/11(火) 10:18 -

引用なし
パスワード
   ウィンドウの×ボタンを消す方法をネットで探していたら、
次のようなサイトを見つけました。

http://park11.wakwak.com/~miko/Excel_Note/03-01_gamen.htm#03-01-01

どうやら、下記のコードで×ボタンを消せるようです。
(長いのでAPI関数宣言は省きます。)

Public Sub HideSysMenu()
 Dim Ret As Long
 Dim hWnd As Long
 Dim Wnd_STYLE As Long
 hWnd = GetActiveWindow()
 Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
 Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
 Ret = SetWindowLong(hWnd, GWL_STYLE, Wnd_STYLE)
 Ret = DrawMenuBar(hWnd)
End Sub


ここで、疑問なのですが、

 Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)

とはどういうことなのでしょうか?
And (Not WS_SYSMENU)
というのがわかりません。

よろしくお願いします。

【40305】Re:(Not WS_SYSMENU)ってどういう意味...
発言  Statis  - 06/7/11(火) 10:26 -

引用なし
パスワード
   こんにちは
記載のホームページの管理さんにお聞きになるのが良いと思いますよ。

【40306】Re:(Not WS_SYSMENU)ってどういう意味...
質問  mutu  - 06/7/11(火) 10:35 -

引用なし
パスワード
   メールでの質問は受け付けていないそうなので、
お忙しい中申し訳ありませんが、よろしくお願いします。


引用元:
http://park11.wakwak.com/~miko/Excel_Note/03-01_gamen.htm#03-01-01

Public Sub RestoreSysMenu()
 Dim Ret As Long
 Dim hWnd As Long
 Dim Wnd_STYLE As Long
 hWnd = GetActiveWindow()
 Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
 Wnd_STYLE = Wnd_STYLE Or WS_SYSMENU
 Ret = SetWindowLong(hWnd, GWL_STYLE, Wnd_STYLE)
 Ret = DrawMenuBar(hWnd)
End Sub

また、×ボタンを復活させるときに、
 Wnd_STYLE = Wnd_STYLE And WS_SYSMENU

ではなく、
 Wnd_STYLE = Wnd_STYLE Or WS_SYSMENU

にしているのも理解がしにくいところです。

重ねてよろしくお願いします。

【40308】Re:(Not WS_SYSMENU)ってどういう意味...
発言  Blue  - 06/7/11(火) 10:53 -

引用なし
パスワード
   > 理解がしにくいところです。
フラグというか、論理演算について調べてみるとよいでしょう。

【40309】Re:(Not WS_SYSMENU)ってどういう意味...
発言  ichinose  - 06/7/11(火) 10:59 -

引用なし
パスワード
   ▼mutu さん:
こんにちは。


>
>http://park11.wakwak.com/~miko/Excel_Note/03-01_gamen.htm#03-01-01
>
>どうやら、下記のコードで×ボタンを消せるようです。
>(長いのでAPI関数宣言は省きます。)
>
>Public Sub HideSysMenu()
> Dim Ret As Long
> Dim hWnd As Long
> Dim Wnd_STYLE As Long
> hWnd = GetActiveWindow()
> Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
> Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
> Ret = SetWindowLong(hWnd, GWL_STYLE, Wnd_STYLE)
> Ret = DrawMenuBar(hWnd)
>End Sub
>
>
>ここで、疑問なのですが、
>
> Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
これは、Bit単位で and演算を行っているのです。

Wnd_Styleには、

> Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)

APIで取得したウインドウ情報が格納されています。

この> Wnd_STYLE はこんな形式の情報になっています。

http://yokohama.cool.ne.jp/chokuto/urawaza/prm/window_style.html

これを見ると、xボタンを付けるか否かは、2^19BIT目がONかOFFの設定になっています。

2^19-----&H80000 です。


よって、
> Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)

は、この2^19BitのみをOFFにする演算です。
(他のビットに影響を与えない演算です)

逆に

> Wnd_STYLE = Wnd_STYLE Or WS_SYSMENU

は、2^19BitをONにする演算です。
(他のビットに影響を与えない演算です)


ということです。低級言語を扱うとこういう概念は良く出てきますよ!!


>
>とはどういうことなのでしょうか?
>And (Not WS_SYSMENU)
>というのがわかりません。
>
>よろしくお願いします。

【40310】Re:(Not WS_SYSMENU)ってどういう意味...
発言  ひげくま  - 06/7/11(火) 11:02 -

引用なし
パスワード
   この動作に関しては、まったく解っていませんが、コードに関してはある程度想像できるので、参考までに。

>どうやら、下記のコードで×ボタンを消せるようです。
> Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)

>また、×ボタンを復活させるときに、
> Wnd_STYLE = Wnd_STYLE And WS_SYSMENU
>
>ではなく、
> Wnd_STYLE = Wnd_STYLE Or WS_SYSMENU
>
>にしているのも理解がしにくいところです。

たぶん、Wnd_STYLE のどれかのビットが、×ボタンの表示/非表示のフラグになっていると思われます。
フラグがHiのときは、×ボタン表示で、Loのときは、×ボタン非表示。

そして、WS_SYSMENUは、×ボタン表示フラグがあるビットだけ立っている定数だと思います。
もし、×ボタン表示フラグがbit2だとすれば、WS_SYSMENUは04H(00000100B)ですね。(実際にはLongですが、便宜上Byte表記にしてあります)

×ボタンを非表示にするためには、×ボタン表示フラグだけをLoにして、それ以外のビットを変えないためには、そのビットだけLoでそれ以外のビットはHiの値でANDをとる必要があります。
11111011B = Not 00000100B ですね。
なので、And (Not WS_SYSMENU) となります。

また、×ボタンを表示するには、×ボタン表示フラグだけをHiにする必要があるので、00000100BでORをとる必要があります。
なので、Or WS_SYSMENU ですね。
もし、×ボタンを復活させるときに、And WS_SYSMENU にしてしまうと、×ボタン表示フラグは変わらずに、それ以外のビットがすべてLoになってしまい、期待した動作とはまったく別の動作をすることになります。

この考え方で、だいたいは合っていると思います。
×ボタン表示フラグの位置がbit2である、ということは、まったくのでたらめですが。

【40311】Re:(Not WS_SYSMENU)ってどういう意味...
発言  ひげくま  - 06/7/11(火) 11:05 -

引用なし
パスワード
   自己レス

既に、お二人から詳しい回答がついていましたね。
書くのに時間がかかったため、既にお二人から回答がついていることに気づかずに、曖昧な回答を書いてしまいました。

【40314】Re:(Not WS_SYSMENU)ってどういう意味...
お礼  mutu  - 06/7/11(火) 12:36 -

引用なし
パスワード
   大変わかりやすい解説、
ありがとうございました。
おかげさまで、よくわかりました。



【40316】SetWindowLongPtrを使うには?
質問  mutu  - 06/7/11(火) 13:47 -

引用なし
パスワード
   ネットで情報を集めていると、

SetWindowLong(A)
この関数は SetWindowLongPtr に取って代わられています。32ビット版と64ビット版の Windows で共通して利用できるコードを記述する場合には、 SetWindowLongPtr 関数を使用する必要があります。
引用元:
http://yokohama.cool.ne.jp/chokuto/urawaza/api/SetWindowLong.html


とありましたので、SetWindowLongPtrを使うことにしました。

下記は最初に省略したAPI関数宣言部を含めたコードです。
引用元:http://park11.wakwak.com/~miko/Excel_Note/03-01_gamen.htm#03-01-01

Private Const GWL_STYLE = (-16)
Private Const WS_SYSMENU = &H80000
Private Declare Function GetWindowLong Lib "user32" _
   Alias "GetWindowLongA" _
   (ByVal hWnd As Long, _
   ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" _
   Alias "SetWindowLongA" _
   (ByVal hWnd As Long, _
   ByVal nIndex As Long, _
   ByVal dwNewLong As Long) As Long
Private Declare Function GetActiveWindow Lib "user32" () As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long

Public Sub HideSysMenu()
 Dim Ret As Long
 Dim hWnd As Long
 Dim Wnd_STYLE As Long
 hWnd = GetActiveWindow()
 Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
 Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
 Ret = SetWindowLong(hWnd, GWL_STYLE, Wnd_STYLE)
 Ret = DrawMenuBar(hWnd)
End Sub

Public Sub RestoreSysMenu()
 Dim Ret As Long
 Dim hWnd As Long
 Dim Wnd_STYLE As Long
 hWnd = GetActiveWindow()
 Wnd_STYLE = GetWindowLong(hWnd, GWL_STYLE)
 Wnd_STYLE = Wnd_STYLE Or WS_SYSMENU
 Ret = SetWindowLong(hWnd, GWL_STYLE, Wnd_STYLE)
 Ret = DrawMenuBar(hWnd)
End Sub


いま、このコードの
SetWindowLongとGetActiveWindowをそれぞれ
SetWindowLongPtrとGetActiveWindowPtrに代えてみたのですがうまくいきません。
どうしたらよろしいのでしょうか?
下記のコードが変更したものです。
(単純にPtrを後ろにつけてみました。)

Private Const GWL_STYLE = (-16)
Private Const WS_SYSMENU = &H80000
Private Declare Function GetWindowLongPtr Lib "user32" _
   Alias "GetWindowLongA" _
   (ByVal hWnd As Long, _
   ByVal nIndex As Long) As Long
Private Declare Function SetWindowLongPtr Lib "user32" _
   Alias "SetWindowLongA" _
   (ByVal hWnd As Long, _
   ByVal nIndex As Long, _
   ByVal dwNewLong As Long_PTR) As Long
Private Declare Function GetActiveWindow Lib "user32" () As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long

Public Sub HideSysMenu()
 Dim Ret As Long
 Dim hWnd As Long
 Dim Wnd_STYLE As Long
 hWnd = GetActiveWindow()
 Wnd_STYLE = GetWindowLongPtr(hWnd, GWL_STYLE)
 Wnd_STYLE = Wnd_STYLE And (Not WS_SYSMENU)
 Ret = SetWindowLongPtr(hWnd, GWL_STYLE, Wnd_STYLE)
 Ret = DrawMenuBar(hWnd)
End Sub

Public Sub RestoreSysMenu()
 Dim Ret As Long
 Dim hWnd As Long
 Dim Wnd_STYLE As Long
 hWnd = GetActiveWindow()
 Wnd_STYLE = GetWindowLongPtr(hWnd, GWL_STYLE)
 Wnd_STYLE = Wnd_STYLE Or WS_SYSMENU
 Ret = SetWindowLongPtr(hWnd, GWL_STYLE, Wnd_STYLE)
 Ret = DrawMenuBar(hWnd)
End Sub

よろしくお願いします。

【40318】Re:SetWindowLongPtrを使うには?
発言  Blue  - 06/7/11(火) 14:00 -

引用なし
パスワード
   >Private Declare Function GetWindowLongPtr Lib "user32" _
>   Alias "GetWindowLongA" _
>   (ByVal hWnd As Long, _
>   ByVal nIndex As Long) As Long
まず、Aliasの関数名を変えないとだめです。
(Libに指定した)user32.dllの(Aliasにしていした)GetWindowLongAという関数を
(Declareで指定した)GetWindowLongPtrという関数として使いますという宣言文になります。

ついでに
>Private Declare Function SetWindowLongPtr Lib "user32" _
>   Alias "SetWindowLongA" _
>   (ByVal hWnd As Long, _
>   ByVal nIndex As Long, _
>   ByVal dwNewLong As Long_PTR) As Long
のLong_PTR型はVBAにはない型です。これは64ビット環境と32ビット環境で大きさが変わるようなつくりになっています。
よって32ビット環境では、Long型でよいはず。


WinAPIを使いこなすには多少なりともC言語の知識があったほうがよいです。

http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpwinui/html/_Win32_GetWindowLongPtr.asp
LONG_PTR GetWindowLongPtr(
 HWND hWnd, // ウィンドウのハンドル
 int nIndex // 取得する値のオフセット
);

Private Declare Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" _
  (ByVal hWnd As Long, ByVal nIndex As Long) As Long

http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpwinui/html/_Win32_SetWindowLongPtr.asp
LONG_PTR SetWindowLongPtr(
 HWND hWnd,      // ウィンドウのハンドル
 int nIndex,     // 変更する値のオフセット
 LONG_PTR dwNewLong  // 新しい値
);

Private Declare Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" _
  (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

かな。試していませんけど。

【40322】Re:SetWindowLongPtrを使うには?
質問  mutu  - 06/7/11(火) 15:16 -

引用なし
パスワード
   回答ありがとうございます。

教えてもらったのを試そうと思ったのですが、
SetWindowLongを
SetWindowLongPtrにするという以前に

上記のコード(Ptrを追加する前のコード)を追加したことによって、

Worksheets(sheet1).Visible = False

がVBエラーになるようになっていました。

どうすれば、回避できるのでしょうか?

WindowsXP,
Excel2003SP2を使っています。


いま、下記サイトを読み進めていますが、いまいち解決法が見えてきません。
https://www.microsoft.com/japan/msdn/columns/office/office03082001.asp

【40323】Re:SetWindowLongPtrを使うには?
発言  Blue  - 06/7/11(火) 15:22 -

引用なし
パスワード
   > Worksheets(sheet1).Visible = False
Worksheets("sheet1").Visible = False
なのでは?

sheet1と指定すると、Sheetオブジェクトになってしまうかも。
シート名ならばきちんと文字列として認識させましょう。

【40324】Re:SetWindowLongPtrを使うには?
お礼  mutu  - 06/7/11(火) 16:23 -

引用なし
パスワード
   ▼Blue さん:
>> Worksheets(sheet1).Visible = False
>Worksheets("sheet1").Visible = False
>なのでは?

はい、
この間違いと、
下記の処理でワークブックの保護をしていたのが原因だったようです。
大変お騒がせしました。

  'アクティブブックのボタンを消す
  ActiveWorkbook.Protect Structure:=False, Windows:=True

  'アクティブブックのボタンを元に戻す
  ActiveWorkbook.Protect Structure:=False, Windows:=False

引用元:http://www.k1simplify.com/vba/tipsleaf/leaf235.html

【40325】Re:SetWindowLongPtrを使うには?
発言  Blue  - 06/7/11(火) 16:46 -

引用なし
パスワード
   ていうか、やっぱり「GetWindowLongPtr」「SetWindowLongPtr」はDLLの関数ではないですね。

実際使おうとするとDLLにないと言われてしまったところ(Xp SP2/Office2003)、
Dependency WalkerというDLL内の関数を見ることができるツールで確認したところ、
「GetWindowLongPtr」「SetWindowLongPtr」は存在しませんでした。

> この関数は SetWindowLongPtr に取って代わられています。32ビット版と64ビッ
> ト版の Windows で共通して利用できるコードを記述する場合には、
> SetWindowLongPtr 関数を使用する必要があります。
これは、ヘッダファイルをつかってコーディングするつまり「C/C++」の時の注意事項だったのでしょう。

よって、ヘッダファイルを使わずに、Declear宣言していくVBAでは、使えないのではないでしょう。

まぁ、Declare宣言する以上、64ビット環境になればまた書き直す羽目になると思うので
とりあえず「GetWindowLong」「SetWindowLong」を利用すればよいです。
(ちゅうか、Win32 Declare宣言なんてほとんど書き直しでしょ。なんせWin32 APIですから)


(以下、参考程度。わからなければ読まなくてもよいです。)
user32.dllってことは32ビット用のDLLですから、64ビット用はuser64.dllとかになって、
おそらくヘッダで

#ifdef 64ビット環境である
 #define GetWindowLongPtrA GetWinodwLongPtrA // user64.dllには定義されている(予想)
 #define GetWindowLongPtrW GetWindowLongPtrW // user64.dllには定義されている(予想)
#else
 #define GetWindowLongPtrA GetWindowLongA
 #define GetWindowLongPtrW GetWindowLongW
#endif
#ifdef UNICODE
 #define GetWindowLongPtr GetWindowLongPtrW
#else
 #define GetWindowLongPtr GetWindowLongPtrA
#endif

てなかんじになっているんでしょう。(最新のPlatform SDK)

【40330】Re:SetWindowLongPtrを使うには?
お礼  mutu  - 06/7/11(火) 17:21 -

引用なし
パスワード
   ありがとうございます。
VBAでは使わなくていいということがわかっただけでも安心しました。


VBA、奥が深いですね。
まだまだ、勉強が足りないと痛感しています。

7251 / 13644 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free