[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『ツールバーに自作のアイコンを追加したい』(しのみや)
ツールバーに自作のアイコンを追加しようとしていて、 以下の記述をxlaで保存し、アドイン化しました。
Private Sub Workbook_AddinInstall()
On Error Resume Next
Application.CommandBars("パレット").Delete
Dim myBar As CommandBar, myButton As CommandBarButton Set myBar = Application.CommandBars.Add(Position:=msoBarTop) myBar.Name = "パレット"
Set myButton = myBar.Controls.Add(Type:=msoControlButton)
myButton.OnAction = "RGB" myButton.Caption = "RGB" myButton.FaceId = 59
myBar.Visible = True
On Error GoTo 0
End Sub
ここでmyButton.FaceId = 59の部分を自分が作成したアイコンに変更しようとしています。 アイコンは、ビットマップで保存したものです。
どのようにしたらよいでしょうか。
< 使用 Excel:Excel2010、使用 OS:Windows10 >
ただ、このアドインを人と共有しようと考えておりまして、
cに置いておけないのです。
どのようにしたら対応できますでしょうか。
(しのみや) 2020/12/16(水) 13:15
myButton.Picture = UserForm1.Image1.Picture
とかが簡単でしょうか。
(チオチモリン ) 2020/12/16(水) 14:07
ありがとうございます 必要な結果が得られました ユーザーフォームに置いてそれを読み込みに行く方法があるのですね (しのみや) 2020/12/16(水) 15:19
もうひとつ教えていただきたいことが出てきましたのでよろしくお願いします。
ツールバーにオプションボタンを置きたくて、
UserFormにFrameを置いて、オプションボタンを3つ置きました。
myButton.Picture = UserForm1.Frame1
このような感じでできるのかな…と試してみているのですが どうやら違うようです。
どのようにしたらよいでしょうか。 (しのみや) 2020/12/18(金) 09:55
見た目だけの話じゃなくって、 ちゃんとオプションボタンとして機能するオプションボタンですよね? RibbonUIの方でもcheckBoxならありますけど、Optionはどうなんだろ? 出来るのかな・・・? 私は見たことありません。
CommandBarのControlは ・Button ・ComboBox ・Popup の3種類なので機能としてはComboBoxがいちばん近いと思いますけどね
Sub Test_Add() On Error Resume Next Application.CommandBars("パレット").Delete On Error GoTo 0
Dim myBar As CommandBar, myCombo As CommandBarComboBox Set myBar = Application.CommandBars.Add(Position:=msoBarTop) myBar.Name = "パレット" Set myCombo = myBar.Controls.Add(Type:=msoControlComboBox) myCombo.Caption = "Combo1" myCombo.AddItem "Option1" myCombo.AddItem "Option2" myCombo.AddItem "Option3" myCombo.OnAction = "Combo1_Click" myBar.Visible = True End Sub Sub Combo1_Click() MsgBox Application.CommandBars("パレット").Controls("Combo1").ListIndex End Sub
(白茶) 2020/12/18(金) 11:40
(MK) 2020/12/18(金) 12:06
無理矢理ですがFaceIdの切替で「ソレっぽく」見せてみましたので追記しときます
Sub Test_Add() On Error Resume Next Application.CommandBars("パレット").Delete On Error GoTo 0
Dim myBar As CommandBar, myCombo As CommandBarComboBox Dim myButton As CommandBarButton Set myBar = Application.CommandBars.Add(Position:=msoBarTop) myBar.Name = "パレット" Set myCombo = myBar.Controls.Add(Type:=msoControlComboBox) myCombo.Caption = "Combo1" myCombo.AddItem "Option1" myCombo.AddItem "Option2" myCombo.AddItem "Option3" myCombo.OnAction = "Combo1_Click"
Dim i As Long For i = 1 To 3 Set myButton = myBar.Controls.Add(Type:=msoControlButton) myButton.Caption = "Button" & i myButton.OnAction = "'Button_Click " & i & "'" myButton.Style = msoButtonIconAndCaption myButton.FaceId = 6083 If i = 1 Then myButton.State = msoButtonDown myButton.FaceId = 6082 End If Next myBar.Visible = True End Sub Sub Combo1_Click() MsgBox Application.CommandBars("パレット").Controls("Combo1").ListIndex End Sub Sub Button_Click(id As String) With Application.CommandBars("パレット") If .Controls("Button" & id).State = msoButtonDown Then Exit Sub Dim myButton As CommandBarControl For Each myButton In .Controls If myButton.Caption Like "Button#" Then myButton.State = msoButtonUp myButton.FaceId = 6083 End If Next .Controls("Button" & id).State = msoButtonDown .Controls("Button" & id).FaceId = 6082 End With End Sub
(白茶) 2020/12/18(金) 13:14
ComboBoxを使わさせてもらおうかなと考えていたところ、 無理やりでも再現されるとは… 今から動きを勉強させてもらいます! (しのみや) 2020/12/18(金) 14:57
FaceIdの切替の頂いた記述をAddinsFileColor0.xlaのThisWorkbookに貼り付けて実行してみたところ、 ツールバーにコンボボックスとボタンの表示はできました。
しかし、Button1をクリックするとエラーメッセージが出ます。
マクロ"\\○○○\Microsoft\Addins\AddinsFileColor0.xla'!'Button_Click 1”を実行できません。 このブックでマクロが使用できないか、またはすべてのマクロが無効になっている可能性があります。
なにか私の貼り付け方が悪いのでしょうか…? (しのみや) 2020/12/18(金) 15:48
すみませんちょっと進めることができました (しのみや) 2020/12/18(金) 15:55
頂いた記述のままですと、 ボタンの表示が ◎Button1 ○Button2 ○Button3となっておりますが、 ↓ ◎あああ ○いいい ○ううう としたいので、
myButton.Caption = "Button" & i ここを myButton.Caption = "あああ" に変えれば良いと思うのですが 変えてしまうと
Sub Button_Click(id As String) がうまく動かないのです。
どのようにしたらよいでしょうか。 (しのみや) 2020/12/18(金) 16:43
まぁ、いろいろやり様はあると思いますけど 例えば・・・
Sub Test_Add() On Error Resume Next Application.CommandBars("パレット").Delete On Error GoTo 0
Dim myBar As CommandBar Dim myButton As CommandBarButton
Set myBar = Application.CommandBars.Add(Position:=msoBarTop) myBar.Name = "パレット"
Set myButton = myBar.Controls.Add(Type:=msoControlButton) myButton.Caption = "あああ" myButton.OnAction = "'Button_Click """ & myButton.Caption & """'" myButton.Style = msoButtonIconAndCaption myButton.FaceId = 6082 myButton.Tag = "Group1" myButton.State = msoButtonDown
Set myButton = myBar.Controls.Add(Type:=msoControlButton) myButton.Caption = "いいい" myButton.OnAction = "'Button_Click """ & myButton.Caption & """'" myButton.Style = msoButtonIconAndCaption myButton.FaceId = 6083 myButton.Tag = "Group1"
Set myButton = myBar.Controls.Add(Type:=msoControlButton) myButton.Caption = "ううう" myButton.OnAction = "'Button_Click """ & myButton.Caption & """'" myButton.Style = msoButtonIconAndCaption myButton.FaceId = 6083 myButton.Tag = "Group1"
myBar.Visible = True End Sub Sub Button_Click(id As String) With Application.CommandBars("パレット") If .Controls(id).State = msoButtonDown Then Exit Sub Dim myButton As CommandBarControl For Each myButton In .Controls If myButton.Tag = "Group1" Then myButton.State = msoButtonUp myButton.FaceId = 6083 End If Next .Controls(id).State = msoButtonDown .Controls(id).FaceId = 6082 End With End Sub
(白茶) 2020/12/18(金) 17:02
参考出品 6083 あるんですね。446,1852,3940あたりで諦めてました。 白茶さん 感謝。 で、私も作ってみました。
Sub Test_Bar_Ctrl_Add() Dim CB As Office.CommandBar Dim i As Long On Error Resume Next Application.CommandBars(CB_Name).Delete '再作成時 Set CB = Application.CommandBars(CB_Name) On Error GoTo 0 If CB Is Nothing Then Set CB = Application.CommandBars.Add(CB_Name, , , True) End If '--- CB.Controls.Add(msoControlButton, 59).OnAction = "TestBtn1" Call OP_作成(CB_Name, "Grp1", "○○,◇◇,■■", 1) '--- CB.Controls.Add(msoControlButton, 59).OnAction = "TestBtn2" Call OP_作成(CB_Name, "Grp2", "あああ,いいい,ううう", 2) CB.Visible = True End Sub Sub TestBtn1() MsgBox OP_Selected(CB_Name, "Grp1") End Sub Sub TestBtn2() MsgBox OP_Selected(CB_Name, "Grp2") End Sub Sub OP_作成(BarName As String, グループ名 As String, 選択肢 As Variant, Optional 初期値 As Long = 1) Dim i As Long Dim CB As Office.CommandBar Set CB = Application.CommandBars(BarName) 選択肢 = Split(選択肢, ",") For i = 0 To UBound(選択肢) With CB.Controls.Add(msoControlButton, 59) .Tag = グループ名 .FaceId = IIf(初期値 = i + 1, 6082, 6083) .Caption = 選択肢(i) .OnAction = "OP_Click" .Style = msoButtonIconAndCaption End With Next CB.Visible = True End Sub Sub OP_Click() Dim CBB As Office.CommandBarButton Dim ClickCBB As Office.CommandBarButton Set ClickCBB = Application.CommandBars.ActionControl For Each CBB In ClickCBB.Parent.Controls If CBB.Tag = ClickCBB.Tag Then CBB.FaceId = 6083 Next ClickCBB.FaceId = 6082 End Sub Function OP_Selected(BarName As String, グループ名 As String) As String Dim CBB As Office.CommandBarButton For Each CBB In Application.CommandBars(BarName).Controls If CBB.Tag = グループ名 And CBB.FaceId = 6082 Then OP_Selected = CBB.Caption: Exit For Next End Function
(チオチモリン ) 2020/12/19(土) 10:17
忘れてました。 モジュールの先頭に Const CB_Name As String = "TestBar"’任意 を追加してください。 (チオチモリン ) 2020/12/19(土) 10:33
ちなみに9631と9632でCheckBoxのオン/オフも表現出来そうですよ。
手持ちの道具で22714まで並べて眺めてみたんですけど、 オフ時のイメージは1個ずつしか無さそうでした。
(白茶) 2020/12/21(月) 08:48
すぐ回答頂いているのに、返信遅くてすみません。 白茶さんのFaceIdの記述でオプションボタンの必要な動きが得られました。
こんな風にできるのかな?というのがもう一つ出て来ましたので、よろしくお願いします。
アドインを2つ追加したとします。
AddinsFileColor0.xla ◎あああ ○いいい ○ううう ←Application.CommandBars("パレット0")
AddinsFileColor1.xla ■□●○▲△ ←Application.CommandBars("パレット1")
◎あああが選択されていて、パレット1の■をクリックしたときに、Aという動作 ◎あああが選択されていて、パレット1の□をクリックしたときに、Bという動作 ◎あああが選択されていて、パレット1の●をクリックしたときに、Cという動作 (省略) ◎いいいが選択されていて、パレット1の■をクリックしたときに、Gという動作 (省略)
このように、動作を分けたいのです。
AddinsFileをまたいで?選択されているもののIDを渡すことはできるのだろうか…と考えております…
もしできなければ、ひとつのAddinsFileする方法にしようかなと考えています。 AddinsFileColor0.xla ◎あああ ○いいい ○ううう ■□●○▲△ ←Application.CommandBars("パレット0")
しかし、 AddinsFileColor1.xlaが9まであるので分けておいたほうが管理もしやすいかなと思っています。
チオチモリン さん 白茶さんの記述を理解するので今のところ頭の中がいっぱいで… また時間を見つけて勉強をさせて頂きたいと思います。 ありがとうございます。 (しのみや) 2020/12/21(月) 11:56
白茶さん
CheckBoxのFaceID情報ありがとうございます。
ついでにチェックボックス版も作ろうかと思いますが、
チェック状態の戻り値を配列にするかカンマ区切りの文字列にするか 悩みますね。
(チオチモリン ) 2020/12/21(月) 14:50
実行トリガーはパレット1の各ボタンなので、 パレット1各ボタンのOnActionに指定したプロシージャの中で、 パレット0の有無を確認した上で、各オプションボタンのFaceIdを調べて分岐させれば良いのではないでしょうか? 今回の場合、アドインが分かれているかどうかは、あまり関係ない様に思いますけど・・・。
>もしできなければ、ひとつのAddinsFileする うーん、どうでしょう・・・ 提示頂いているのはあくまで「例」なのでしょうし、 私も実物を見て言ってる訳じゃないので、あんまり無責任な事は言えないですが、 今回の場合、パレット1は「パレット0ありき」の様ですから、あえて分ける意味があまり感じられません。
通常、アドインは「組織」であったり「業務」であったり、ある程度「大きな括り」でひとつにするのが自然ではないかと思います。 バージョン管理や、配布の問題等、後々の事を考えてなるべく一元的に扱える状態が望ましいのではないかと。
アドイン1が提供する機能とアドイン2が提供する機能に依存関係があるならば、 最低でも一方向の依存関係(アドイン2はアドイン1のアペンドである等)しか許容出来ませんしね。 で、 もしそこに設計上の意図があるが故の分割なのであれば、 「もしできなければ」を判断基準にするのは、ちょっと危なっかしくないでしょうか?
それに関連して、冒頭で気になってはいた事なのですが(すんごい「細かい事」で)、 Workbook_AddinInstallイベントでパレット作るのも、ちょっと気になります。
アドイン固有の設定値(例えば各パレットのオプションボタンの初期値等)を指定したい場合、 アドインファイル自体に保存する事も可能ではありますが、 Program Files配下にアドインを置くならUACの制限を考慮しないといけないので、 UserProfile配下にiniファイルを作ったり、レジストリを使って設定値を覚えさせたりします。
AddinInstallイベントって、そういったアドインの機能「そのもの」ではなく 機能を構築する為の「下準備」に関する動作に使う為のものだと思うんですよね(文脈的な意味では) 例えば↓こんな感じの流れです
Workbook_AddinInstall iniファイルの作成、レジストリの登録 ↓ ---------------------------------------------------------------------------- Workbook_Open ini・レジストリの読み込み → パレットの作成 ↓ ここが日常的に動かす範囲 Workbook_BeforeClose ini・レジストリの保存 → パレットの削除 ↓ ---------------------------------------------------------------------------- Workbook_AddinUninstall iniファイル、レジストリの削除
話が逸れてしまいましたが、 アドインの分割・統合については、その辺を踏まえてご判断された方が良いと思います。
※ あくまでご提示頂いている例を見た限りでの「私見」ですので、あまり真に受けないで下さいね。
(白茶) 2020/12/21(月) 15:19
白茶さん 頂いたお話の全部の理解はとてもついていけていない状態ではありますが…
自分で書きながらもAddinを分けておきたい理由が、 これといって根拠があるものではないと感じております…
とても勉強になるお話、ありがとうございます。
チオチモリン さん ただいま頂いた記述を勉強中です。
また行き詰ると思いますので教えて頂けると助かります。 ひとまずひとつのAddinで作ってみて違和感がないか…チャレンジしてみます。
(しのみや) 2020/12/21(月) 15:55
(花村) 2020/12/23(水) 01:51
手持ちの道具ですか。 100個ずつ順番に表示させるUserFormです。 たぶんご想像されてる様な便利なものではありませんよ? (検索機能とか無いです。ただ単に並べるだけ)
一応コード貼っときますね。(しのみやさん、場所お借りします) 作ったのもかなり前ですし、Excel2010でしか使った事ありませんので、動かなかったら諦めて下さい。
ShowModalをFalseにしたUserFormに以下のコードを貼って、適当に呼出して下さい。
Option Explicit Rem API宣言===================================================================================================== Rem クリップボード関係------------------------------------------------------------------------------------------ Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hWnd As LongPtr) As Long Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long Private Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr Private Declare PtrSafe Function CloseClipboard Lib "user32" () As Long Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long Private Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As LongPtr Rem デバイスコンテキスト関係------------------------------------------------------------------------------------ Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As LongPtr) As LongPtr Private Declare PtrSafe Function SelectObject Lib "gdi32" (ByVal hDC As LongPtr, ByVal hObject As LongPtr) As LongPtr Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hDC As LongPtr) As Long Private Const CF_BITMAP = 2& Rem DIBit関係--------------------------------------------------------------------------------------------------- Private Declare PtrSafe Function DeleteObject Lib "gdi32" (ByVal hObject As LongPtr) As Long Private Type BITMAPINFOHEADER biSize As Long biWidth As Long biHeight As Long biPlanes As Integer biBitCount As Integer biCompression As Long biSizeImage As Long biXPelsPerMeter As Long biYPelsPerMeter As Long biClrUsed As Long biClrImportant As Long End Type Private Type BITMAPINFO bmiHeader As BITMAPINFOHEADER End Type Private Declare PtrSafe Function GetDIBits Lib "gdi32" ( _ ByVal aHDC As LongPtr, ByVal hBitmap As LongPtr, ByVal nStartScan As Long, ByVal nNumScans As Long, _ lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long Private Const DIB_RGB_COLORS = 0& Private Declare PtrSafe Function SetDIBits Lib "gdi32" ( _ ByVal hDC As LongPtr, ByVal hBitmap As LongPtr, ByVal nStartScan As Long, ByVal nNumScans As Long, _ lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long Private Declare PtrSafe Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long Private Declare PtrSafe Function CreateDIBSection Lib "gdi32" ( _ ByVal hDC As LongPtr, pBitmapInfo As BITMAPINFO, ByVal un As Long, ByVal lplpVoid As LongPtr, _ ByVal handle As LongPtr, ByVal dw As Long) As LongPtr Rem IPicture作成------------------------------------------------------------------------------------------------ Private Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(7) As Byte End Type Private Type PicBmp Size As Long Type As Long hBmp As Long hPal As Long Reserved As Long End Type Private Declare PtrSafe Function OleCreatePictureIndirect Lib "oleaut32" (PicDesc As PicBmp, RefIID As GUID, ByVal fPictureOwnsHandle As LongPtr, IPic As IPicture) As Long Private Const vbPicTypeBitmap = 1& Rem CopyImage--------------------------------------------------------------------------------------------------- Private Declare PtrSafe Function CopyImage Lib "user32" (ByVal handle As LongPtr, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As LongPtr Private Const IMAGE_BITMAP = 0& Private Const LR_CREATEDIBSECTION = &H2000& Rem その他変数・定数============================================================================================ Rem ------------------------------------------------------------------------------------------------------------ Private Const FM_WIDTH As Long = 324 Private Const FM_HEIGHT As Long = 225 Rem ------------------------------------------------------------------------------------------------------------ Private LabelHeader As MSForms.Label Private WithEvents ChkCopyFace As MSForms.CheckBox Private WithEvents FaceCover As MSForms.Label Private LabelIdNum As MSForms.Label Private WithEvents PixelCover As MSForms.Label Private WithEvents ButtonPrev As MSForms.CommandButton Private WithEvents ButtonNext As MSForms.CommandButton Private WithEvents ButtonGoto As MSForms.CommandButton Private WithEvents ButtonZoom As MSForms.CommandButton Private WithEvents ButtonCopy As MSForms.CommandButton Private WithEvents ButtonPaint As MSForms.CommandButton Private WithEvents ButtonList As MSForms.CommandButton Private LabelCap As MSForms.Label Private LabelCap2 As MSForms.Label Private LabelPx As MSForms.Label Rem ------------------------------------------------------------------------------------------------------------ Private IdZero As Long, IdNow As Long, PicNow As IPictureDisp Rem 内部イベント================================================================================================ Private Sub PrepareControls() Dim i As Long Me.Width = FM_WIDTH Me.Height = FM_HEIGHT Set LabelHeader = Me.Controls.Add("Forms.Label.1", "LabelHeader") With LabelHeader .Top = 2: .Height = 9: .Left = 6: .Width = 180 .TextAlign = fmTextAlignCenter End With For i = 0 To 99 With Me.Controls.Add("Forms.Image.1", "Face" & Format$(i, "000")) .Top = 12 + 18 * Int(i / 10): .Height = 18: .Left = 6 + 18 * (i Mod 10): .Width = 18 .SpecialEffect = fmSpecialEffectRaised .BackStyle = fmBackStyleTransparent End With Next Set LabelCap = Me.Controls.Add("Forms.Label.1", "LabelCap") With LabelCap .Top = 12 + 180 + 1.5: .Height = 9: .Left = 6: .Width = 306 End With Set FaceCover = Me.Controls.Add("Forms.Label.1", "FaceCover") With FaceCover .Top = 12: .Height = 180: .Left = 6: .Width = 180 .BackStyle = fmBackStyleTransparent .ControlTipText = "拡大画像の描画/右クリックで画像をファイルに保存" End With Set ButtonPrev = Me.Controls.Add("Forms.CommandButton.1", "ButtonPrev") With ButtonPrev .Top = 6: .Height = 21: .Left = 190: .Width = 21 .PicturePosition = fmPicturePositionCenter .Picture = CommandBars.GetImageMso("MailMergeGoToPreviousRecord", 16, 16) .Accelerator = "," .ControlTipText = "前のページ(&<)" End With Set ButtonNext = Me.Controls.Add("Forms.CommandButton.1", "ButtonNext") With ButtonNext .Top = 6: .Height = 21: .Left = 211: .Width = 21 .PicturePosition = fmPicturePositionCenter .Picture = CommandBars.GetImageMso("MailMergeGoToNextRecord", 16, 16) .Accelerator = "." .ControlTipText = "次のページ(&>)" End With Set ChkCopyFace = Me.Controls.Add("Forms.CheckBox.1", "ChkCopyFace") With ChkCopyFace .Top = 6: .Height = 21: .Left = 234: .Width = 72 .Accelerator = "T" .Caption = "旧画像(T)" .ControlTipText = "CopyFaceを使った古い画像を表示(ちょっと重い)" End With Set ButtonGoto = Me.Controls.Add("Forms.CommandButton.1", "ButtonGoto") With ButtonGoto .Top = 6: .Height = 21: .Left = 237 + 54: .Width = 21 .PicturePosition = fmPicturePositionCenter .Picture = CommandBars.GetImageMso("FindDialog", 16, 16) .Accelerator = "G" .ControlTipText = "指定したIdへジャンプ(&G)" End With Set ButtonZoom = Me.Controls.Add("Forms.CommandButton.1", "ButtonZoom") Set LabelIdNum = Me.Controls.Add("Forms.Label.1", "LabelIdNum") With LabelIdNum .Top = 30: .Height = 9: .Left = 190: .Width = 7.5 * 16 + 3 End With With Me.Controls.Add("Forms.Frame.1", "Frame2") .Top = 39: .Height = 7.5 * 16 + 3: .Left = 190: .Width = 7.5 * 16 + 3 .SpecialEffect = fmSpecialEffectSunken .PictureTiling = True Set .Picture = CreateCheckeredPattern(&HE5E5E5, &HFFFFFF, 5) For i = 0 To 255 With .Controls.Add("Forms.Label.1", "Pixel" & Format$(i, "000")) .Top = 7.5 * Int(i / 16): .Height = 7.5: .Left = 7.5 * (i Mod 16): .Width = 7.5 .BackStyle = fmBackStyleTransparent End With Next Set PixelCover = .Controls.Add("Forms.Label.1", "PixelCover") With PixelCover .Height = 7.5 * 16: .Width = 7.5 * 16 .BackStyle = fmBackStyleTransparent .ControlTipText = "透過色の設定/解除" End With End With Set LabelCap2 = Me.Controls.Add("Forms.Label.1", "LabelCap2") With LabelCap2 .Top = 39 + 7.5 * 16 + 3: .Height = 9: .Left = 190: .Width = 7.5 * 16 + 3 End With With ButtonZoom .Top = 39 + 7.5 * 16 + 12: .Height = 21: .Left = 190: .Width = 21 '42 .PicturePosition = fmPicturePositionCenter .Picture = CommandBars.GetImageMso("ZoomIn", 16, 16) .Accelerator = "Z" .ControlTipText = "このフォーム自身を拡大/縮小(&Z)" End With Set ButtonPaint = Me.Controls.Add("Forms.CommandButton.1", "ButtonPaint") With ButtonPaint .Top = 39 + 7.5 * 16 + 12: .Height = 21: .Left = 190 + 21.75: .Width = 39 .Accelerator = "P" .Caption = "塗絵(P)" .ControlTipText = "選択中の画像でセル塗り絵を作成" End With Set ButtonList = Me.Controls.Add("Forms.CommandButton.1", "ButtonList") With ButtonList .Top = 39 + 7.5 * 16 + 12: .Height = 21: .Left = 190 + 21.75 + 39.75: .Width = 39 .Accelerator = "L" .Caption = "書出(L)" .ControlTipText = "現在の画像一覧(100個分)を新規シートに書き出し" End With Set ButtonCopy = Me.Controls.Add("Forms.CommandButton.1", "ButtonCopy") With ButtonCopy .Top = 39 + 7.5 * 16 + 12: .Height = 21: .Left = 291: .Width = 21 .PicturePosition = fmPicturePositionCenter .Picture = CommandBars.GetImageMso("Copy", 16, 16) .Accelerator = "C" .ControlTipText = "選択中の画像をクリップボードにコピー(&C)" End With End Sub
Private Sub UserForm_Initialize() Call PrepareControls Call UpdateImageLabels(IdZero) End Sub Private Sub UserForm_Terminate() Set PicNow = Nothing End Sub Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) If Not LabelCap Is Nothing Then LabelCap.Caption = Empty If Not LabelCap2 Is Nothing Then LabelCap2.Caption = Empty If Not LabelPx Is Nothing Then LabelPx.BorderStyle = fmBorderStyleNone End Sub Private Sub ButtonPrev_Click() StartId = StartId - 100 End Sub Private Sub ButtonNext_Click() StartId = StartId + 100 End Sub Private Sub ButtonGoto_Click() Dim i As Variant i = InputBox("番号を入力") If IsNumeric(i) Then CurrentId = CLng(i) End Sub Private Sub ChkCopyFace_Change() Call UpdateImageLabels(IdZero, ChkCopyFace.Value) Set PicNow = GetImagefromFaceId(IdNow, ChkCopyFace.Value) Call UpdatePixelLabels(PicNow.handle) End Sub Private Sub FaceCover_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) If x < 0 Or y < 0 Then Exit Sub If x > FaceCover.Width Or y > FaceCover.Height Then Exit Sub CurrentId = IdZero + Int(y / 18) * 10 + Int(x / 18) If PicNow Is Nothing Then Exit Sub If Button = 2 Then Dim aPath As String, fExist As Boolean aPath = Format$(IdNow, "00000") & ".bmp" With CreateObject("Scripting.FileSystemObject") Do aPath = Application.GetSaveAsFilename(aPath, "ビットマップ,*.bmp,All file,*.*") If aPath = "False" Then Exit Sub fExist = .FileExists(aPath) If fExist Then If MsgBox(.GetFileName(aPath) & " は既に存在します。" & vbCrLf & "上書きしますか?", _ vbYesNo + vbExclamation, "上書き保存の確認") = vbYes Then Exit Do End If Loop While fExist End With SavePicture PicNow, aPath End If End Sub Private Sub FaceCover_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) If x < 0 Or y < 0 Then Exit Sub If x > FaceCover.Width Or y > FaceCover.Height Then Exit Sub Dim i As Long i = Int(y / 18) * 10 + Int(x / 18) If i > 99 Then Exit Sub LabelCap.Caption = Me.Controls("Face" & Format$(i, "000")).ControlTipText End Sub Private Sub PixelCover_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) If x < 0 Or y < 0 Then Exit Sub If x > PixelCover.Width Or y > PixelCover.Height Then Exit Sub Dim i As Long, bk As fmBackStyle, cl As Long With Me.Controls("Pixel" & Format$(Int(y / 7.5) * 16 + Int(x / 7.5), "000")) bk = .BackStyle bk = IIf(bk = fmBackStyleOpaque, fmBackStyleTransparent, fmBackStyleOpaque) cl = .BackColor End With For i = 0 To 255 With Me.Controls("Pixel" & Format$(i, "000")) .BackStyle = fmBackStyleOpaque If .BackColor = cl Then .BackStyle = bk End With Next End Sub Private Sub PixelCover_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single) If Not LabelPx Is Nothing Then LabelPx.BorderStyle = fmBorderStyleNone If x < 0 Or y < 0 Then Exit Sub If x > PixelCover.Width Or y > PixelCover.Height Then Exit Sub Dim i As Long i = Int(y / 7.5) * 16 + Int(x / 7.5) If i > 255 Then Exit Sub Set LabelPx = Me.Controls("Pixel" & Format$(i, "000")) With LabelPx LabelCap2.Caption = .ControlTipText .BorderStyle = fmBorderStyleSingle .BorderColor = IIf(GetYfromRGB(SysColor2RGB(.BackColor)) < 0.5!, &HFFFFFF, &H0&) End With End Sub Private Sub ButtonCopy_Click() If Not PicNow Is Nothing Then Dim Pic As IPictureDisp, hBmp As LongPtr Set Pic = Me.Controls("Face" & Format$(IdNow - IdZero, "000")).Picture Rem Pic.handleをそのままクリップボードに持っていくと、 Rem IPictureの破棄、あるいは別のビットマップオブジェクトが設定された時点で Rem 現ビットマップオブジェクトも破棄されるのでコピーをクリップボードに持っていく Rem あとDIBセクションとしてコピーすると貼り付け時に絵が認識できないのでフラグなしでコピー hBmp = CopyImage(Pic.handle, IMAGE_BITMAP, 0&, 0&, 0&) Call CopyBmptoClipboard(hBmp) Call DeleteObject(hBmp) End If End Sub Private Sub ButtonZoom_Click() Dim tBarHeight As Single tBarHeight = Me.Height - Me.InsideHeight If Me.Zoom = 100 Then Me.Zoom = 200 Me.Width = FM_WIDTH * 2 Me.Height = FM_HEIGHT * 2 - tBarHeight ButtonZoom.Picture = CommandBars.GetImageMso("ZoomOut", 16, 16) Else Me.Zoom = 100 Me.Width = FM_WIDTH Me.Height = FM_HEIGHT ButtonZoom.Picture = CommandBars.GetImageMso("ZoomIn", 16, 16) End If End Sub Private Sub ButtonPaint_Click() If PicNow Is Nothing Then Exit Sub Dim w As Single, c As Range, i As Long If ActiveWorkbook Is Nothing Then Workbooks.Add If ActiveWorkbook.Path <> "" Or Not ActiveWorkbook.Saved Then Workbooks.Add With Cells(1, 1) For w = Cells(1, 1).ColumnWidth To 0 Step -0.75 Cells(1, 1).ColumnWidth = w If Cells(1, 1).Width <= Cells(1, 1).Height Then Exit For Next End With Cells(1, 1).Resize(, 17).Columns.ColumnWidth = w With Cells(2, 2).Resize(16, 16) For Each c In .Cells With Me.Controls("Pixel" & Format$(i, "000")) If .BackStyle = fmBackStyleOpaque Then c.Interior.Color = .BackColor End With i = i + 1 Next With .Borders .LineStyle = xlContinuous .Weight = xlThin .Item(xlInsideHorizontal).LineStyle = xlNone .Item(xlInsideVertical).LineStyle = xlNone End With End With End Sub Private Sub ButtonList_Click() If MsgBox(IdZero & " 〜 " & IdZero + 99 & " までのイメージを出力します", vbInformation + vbOKCancel) = vbCancel Then Exit Sub Call CreateFaceImageList(IdZero, IdZero + 99) End Sub Rem プロパティ================================================================================================== Private Property Get CurrentId() As Long CurrentId = IdNow End Property Private Property Let CurrentId(ByVal newId As Long) If newId < 0 Then newId = 0 If IdNow = newId Then Exit Property Dim i As Long IdNow = newId Set PicNow = GetImagefromFaceId(IdNow, ChkCopyFace.Value) LabelIdNum.Caption = Format$(IdNow, "00000") & " " & GetControlNamesFromId(IdNow) StartId = IdNow If PicNow Is Nothing Then For i = 0 To 255 With Me.Controls("Pixel" & Format$(i, "000")) .BackColor = &H80000005 End With Next Else Call UpdatePixelLabels(PicNow.handle) End If End Property Private Property Get StartId() As Long StartId = IdZero End Property Private Property Let StartId(ByVal newId As Long) If newId < 0 Then newId = 0 newId = Int(newId / 100) * 100 If IdZero = newId Then Exit Property IdZero = newId Call UpdateImageLabels(IdZero, ChkCopyFace.Value) End Property Private Sub UpdateImageLabels(ByVal StartNum As Long, Optional UseCopyFace As Boolean) Dim i As Long, Cap As String i = StartNum For i = 0 To 99 With Me.Controls("Face" & Format$(i, "000")) Set .Picture = GetImagefromFaceId(StartNum + i, UseCopyFace) .ControlTipText = "ID:" & Format$(StartNum + i, "00000") .SpecialEffect = fmSpecialEffectRaised If .Picture Is Nothing Then .SpecialEffect = fmSpecialEffectEtched Cap = GetControlNamesFromId(StartNum + i) If Len(Cap) > 0 Then .ControlTipText = .ControlTipText & ": " & Cap .SpecialEffect = fmSpecialEffectSunken End If End With Next LabelHeader.Caption = StartNum & " to " & StartNum + 99 End Sub Private Sub UpdatePixelLabels(hBmp As LongPtr) Dim v() As Variant, i As Long, r As Long, c As Long Dim vRGB() As Variant v = GetRGBsofBmp(hBmp, 16, 16) For r = 1 To 16 For c = 1 To 16 With Me.Controls("Pixel" & Format$(i, "000")) .BackColor = v(r, c) vRGB = SplitRGB(CLng(v(r, c))) .ControlTipText = "x=" & c & " y=" & r & " RGB:" & Join(vRGB, ",") .BackStyle = fmBackStyleOpaque End With i = i + 1 Next Next End Sub Rem メソッド============================================================================================================ Public Sub CreateFaceImageList(idFrom As Long, idTo As Long) Dim Btn As CommandBarButton, Pic As IPictureDisp, i As Long, r As Long Dim hBmp As LongPtr Dim ErrNum As Long If ActiveWorkbook Is Nothing Then Workbooks.Add If ActiveWorkbook.Path <> "" Or Not ActiveWorkbook.Saved Then Workbooks.Add [A1:F1] = [{"FaceId",".CopyFace",".Picture",".Mask","MaskedImage",".Caption"}] With CommandBars.Add(Name:="test", temporary:=True) Set Btn = .Controls.Add(Type:=msoControlButton, temporary:=True) r = 2 For i = idFrom To idTo Cells(r, 1) = i On Error Resume Next Btn.FaceId = i ErrNum = Err.Number On Error GoTo 0 If ErrNum = 0 Then Rem CopyFace画像 Btn.CopyFace Cells(r, 2).Select ActiveSheet.Paste Rem 素のPicture画像 Set Pic = Btn.Picture Call CopyBmptoClipboard(Pic.handle) Cells(r, 3).Select ActiveSheet.Paste Rem Mask画像 Set Pic = Btn.Mask Call CopyBmptoClipboard(Pic.handle) Cells(r, 4).Select ActiveSheet.Paste Rem マスク適用後のPicture画像 hBmp = CopyImage(Btn.Picture.handle, IMAGE_BITMAP, 0&, 0&, 0&) Call SetMask(hBmp, Btn.Mask.handle, 16, 16) Call CopyBmptoClipboard(hBmp) Call DeleteObject(hBmp) Cells(r, 5).Select ActiveSheet.Paste Else Cells(r, 2).Value = "(No Image)" End If Rem コントロールキャプション Cells(r, 6).Value = GetControlNamesFromId(i) r = r + 1 DoEvents '画面描画維持 Next Btn.Delete .Delete End With End Sub Rem サブルーチン================================================================================================ Private Function GetControlNamesFromId(ID As Long) As String Dim Str As String On Error Resume Next Str = Application.CommandBars.FindControl(ID:=ID).Caption On Error GoTo 0 GetControlNamesFromId = Str End Function Private Function GetImagefromFaceId(FaceIdNumber As Long, Optional UseCopyFace As Boolean) As IPictureDisp Const BarName As String = "TMP_GetImagefromFaceId" On Error Resume Next CommandBars(BarName).Delete On Error GoTo 0 Dim Cb As CommandBarButton, hBmp As LongPtr, bkColor As Long, ErrNum As Long bkColor = Me.BackColor With CommandBars.Add(Name:=BarName, temporary:=True) Set Cb = .Controls.Add(Type:=msoControlButton, temporary:=True) With Cb On Error Resume Next .FaceId = FaceIdNumber ErrNum = Err.Number On Error GoTo 0 If ErrNum = 0 Then If UseCopyFace Then .CopyFace hBmp = CopyImage(GetBmpfromClipboard, IMAGE_BITMAP, 0&, 0&, LR_CREATEDIBSECTION) Else hBmp = CopyImage(.Picture.handle, IMAGE_BITMAP, 0&, 0&, LR_CREATEDIBSECTION) Call SetMask(hBmp, .Mask.handle, 16, 16, bkColor) End If If hBmp Then Set GetImagefromFaceId = CreatePictureByhBmp(hBmp) End If .Delete End With Set Cb = Nothing .Delete End With End Function Private Function CopyBmptoClipboard(hBmp As LongPtr) As Boolean Call OpenClipboard(0&) Call EmptyClipboard CopyBmptoClipboard = CBool(SetClipboardData(CF_BITMAP, hBmp)) Call CloseClipboard End Function Private Function GetBmpfromClipboard() As LongPtr If IsClipboardFormatAvailable(CF_BITMAP) = 0 Then Exit Function If OpenClipboard(0&) <> 0 Then GetBmpfromClipboard = GetClipboardData(CF_BITMAP) Call CloseClipboard End If End Function Private Function CreatePictureByhBmp(ByVal hBmp As LongPtr, Optional hPal As LongPtr) As IPictureDisp Dim IID_IDispatch As GUID, Bmp As PicBmp With IID_IDispatch .Data1 = &H20400 .Data4(0) = &HC0& .Data4(7) = &H46& End With With Bmp .Size = Len(Bmp) .Type = vbPicTypeBitmap .hBmp = hBmp .hPal = hPal End With Call OleCreatePictureIndirect(Bmp, IID_IDispatch, 1, CreatePictureByhBmp) End Function Private Function GetRGBsofBmp(ByVal hBmp As LongPtr, pxWidth As Long, pxHeight As Long) As Variant Dim Rtn As LongPtr Dim bi As BITMAPINFO Dim hDC As LongPtr, hOld As LongPtr Dim RGBBuff() As Byte, r As Long, c As Long, vRGB() As Variant hDC = CreateCompatibleDC(0&) hOld = SelectObject(hDC, hBmp) With bi.bmiHeader .biSize = Len(bi.bmiHeader) .biWidth = pxWidth .biHeight = -pxHeight 'トップダウン走査 .biPlanes = 1 .biBitCount = 32 .biSizeImage = pxWidth * 4 * pxHeight End With ReDim RGBBuff(1 To pxWidth * 4, 1 To pxHeight) Rtn = GetDIBits(hDC, hBmp, 0&, pxHeight, RGBBuff(1, 1), bi, DIB_RGB_COLORS) Call SelectObject(hDC, hOld) Call DeleteDC(hDC) If Rtn = 0 Then Exit Function ReDim vRGB(1 To pxHeight, 1 To pxWidth) For r = 1 To pxHeight For c = 1 To pxWidth vRGB(r, c) = RGBBuff(c * 4 - 1, r) + RGBBuff(c * 4 - 2, r) * &H100& + RGBBuff(c * 4 - 3, r) * &H100& ^ 2 Next Next GetRGBsofBmp = vRGB End Function Private Function SplitRGB(aRGB As Long, Optional Percentage As Boolean) As Variant Dim i As Long, Ary(0 To 2) As Variant For i = 0 To 2 Ary(i) = (aRGB \ &H100& ^ i) Mod &H100& If Percentage Then Ary(i) = CSng(Ary(i) / &HFF&) Next SplitRGB = Ary End Function Private Function SetMask(ByVal hBmp As LongPtr, ByVal hMask As LongPtr, pxWidth As Long, pxHeight As Long, _ Optional ByVal bkColor As Long = &H8000000F) As Boolean Dim Rtn As LongPtr Dim bi As BITMAPINFO Dim hDC As LongPtr, hOld As LongPtr Dim RGBBuff() As Byte, r As Long, c As Long Dim MaskBuff() As Byte, bkRGB() As Variant, Alpha(0 To 2) As Single hDC = CreateCompatibleDC(0&) hOld = SelectObject(hDC, hBmp) With bi.bmiHeader .biSize = Len(bi.bmiHeader) .biWidth = pxWidth .biHeight = -pxHeight 'トップダウン走査 .biPlanes = 1 .biBitCount = 32 .biSizeImage = pxWidth * 4 * pxHeight End With ReDim RGBBuff(1 To pxWidth * 4, 1 To pxHeight) ReDim MaskBuff(1 To pxWidth * 4, 1 To pxHeight) Rtn = GetDIBits(hDC, hBmp, 0&, pxHeight, RGBBuff(1, 1), bi, DIB_RGB_COLORS) Rtn = GetDIBits(hDC, hMask, 0&, pxHeight, MaskBuff(1, 1), bi, DIB_RGB_COLORS) bkRGB = SplitRGB(SysColor2RGB(bkColor)) For r = 1 To pxHeight For c = 1 To pxWidth Alpha(0) = MaskBuff(c * 4 - 1, r) / &HFF& Alpha(1) = MaskBuff(c * 4 - 2, r) / &HFF& Alpha(2) = MaskBuff(c * 4 - 3, r) / &HFF& RGBBuff(c * 4 - 1, r) = CLng(bkRGB(0) * Alpha(0) + RGBBuff(c * 4 - 1, r) * (1 - Alpha(0))) 'R RGBBuff(c * 4 - 2, r) = CLng(bkRGB(1) * Alpha(1) + RGBBuff(c * 4 - 2, r) * (1 - Alpha(1))) 'G RGBBuff(c * 4 - 3, r) = CLng(bkRGB(2) * Alpha(2) + RGBBuff(c * 4 - 3, r) * (1 - Alpha(2))) 'B Next Next Rtn = SetDIBits(hDC, hBmp, 0&, pxHeight, RGBBuff(1, 1), bi, DIB_RGB_COLORS) Call SelectObject(hDC, hOld) Call DeleteDC(hDC) If Rtn Then SetMask = True End Function Private Function SysColor2RGB(SysCol As Long) As Long If (SysCol And &HFF000000) = &H80000000 Then SysColor2RGB = GetSysColor(SysCol And &HFFFFFF) Else SysColor2RGB = SysCol End If End Function Function GetYfromRGB(aRGB As Long) As Single Const prmR = 0.298912!, prmG = 0.586611!, prmB = 0.114478! Dim vRGB() As Variant vRGB = SplitRGB(aRGB) GetYfromRGB = vRGB(0) * prmR + vRGB(1) * prmG + vRGB(2) * prmB GetYfromRGB = GetYfromRGB / &HFF& If GetYfromRGB > 1! Then GetYfromRGB = 1! If GetYfromRGB < 0! Then GetYfromRGB = 0! End Function Private Function CreateCheckeredPattern(color1 As Long, color2 As Long, pxSize As Long) As IPictureDisp Dim Rtn As LongPtr Dim bi As BITMAPINFO Dim hDC As LongPtr, hOld As LongPtr, hBmp As LongPtr Dim RGBBuff() As Byte, r As Long, c As Long Dim RGB1() As Variant, RGB2() As Variant With bi.bmiHeader .biSize = Len(bi.bmiHeader) .biWidth = pxSize * 2 .biHeight = -pxSize * 2 'トップダウン走査 .biPlanes = 1 .biBitCount = 32 .biSizeImage = (pxSize * 2) * 4 * (pxSize * 2) End With ReDim RGBBuff(1 To (pxSize * 2) * 4, 1 To (pxSize * 2)) For r = 1 To (pxSize * 2) If r <= pxSize Then RGB1 = SplitRGB(color1) RGB2 = SplitRGB(color2) Else RGB1 = SplitRGB(color2) RGB2 = SplitRGB(color1) End If For c = 1 To (pxSize * 2) RGBBuff(c * 4 - 1, r) = IIf(c <= pxSize, RGB1(0), RGB2(0)) 'R RGBBuff(c * 4 - 2, r) = IIf(c <= pxSize, RGB1(1), RGB2(1)) 'G RGBBuff(c * 4 - 3, r) = IIf(c <= pxSize, RGB1(2), RGB2(2)) 'B Next Next hDC = CreateCompatibleDC(0&) hBmp = CreateDIBSection(hDC, bi, DIB_RGB_COLORS, 0&, 0&, 0&) hOld = SelectObject(hDC, hBmp) Rtn = SetDIBits(hDC, hBmp, 0&, pxSize * 2, RGBBuff(1, 1), bi, DIB_RGB_COLORS) Call SelectObject(hDC, hOld) Call DeleteDC(hDC) If Rtn Then Set CreateCheckeredPattern = CreatePictureByhBmp(hBmp) End Function
(白茶) 2020/12/23(水) 15:03
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.