UWSC(PowerShell)で絵と吹き出しを表示する
公式掲示板にイラスト画像を表示して吹き出しを付けたい、というなんとも面倒なお題があがっていました。
これ簡単じゃないし、こういう質問をしちゃう人に回答すると、質問攻めに会いそうで怖いからスルーしてたんですが、ま、質問攻めをスルーするかもしれないけど、答えてみる。
スクリプト
まあ、とりあえず書いてみたぞ。
任意の画像を表示したり、吹き出しを出すなら、.net すなわち PowerShell使おう、というところ。
既知の不具合が二点あって、
- 移動(初回表示含む)直後、メッセージが表示されない
- 長い日本語のメッセージが切れる
bmpBalloon.uws
OPTION EXPLICIT IFB GET_UWSC_NAME = "bmpBalloon.uws" THEN DIM id = BmpBalloon.Start(INPUT("表示するBitmapファイルを指定して")), cmd = EMPTY WHILE cmd <> "exit" cmd = INPUT("[exit]と入力すると終了します") BmpBalloon.SetMsg(id, cmd) WEND SLEEP(0.5) ENDIF MODULE BmpBalloon TEXTBLOCK _script Add-Type -AssemblyName System.Windows.Forms $formMain = New-Object System.Windows.Forms.Form $formMain.Text = '$$formName$$' $bmp = New-Object System.Drawing.Bitmap '$$bmpPath$$' $transColor = $bmp.GetPixel($$x$$, $$y$$) $formMain.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None $textBoxCmd = New-Object System.Windows.Forms.TextBox $textBoxX = New-Object System.Windows.Forms.TextBox $textBoxY = New-Object System.Windows.Forms.TextBox $textBoxDisplay = New-Object System.Windows.Forms.TextBox $bmp.MakeTransparent($transColor) $formMain.Size = New-Object System.Drawing.Size($bmp.Width, $bmp.Height) $formMain.BackgroundImage = $bmp $formMain.BackColor = $transColor $formMain.TransparencyKey = $transColor $textBoxCmd.Location = New-Object System.Drawing.Point($bmp.Width, $bmp.Height) $textBoxX.Location = New-Object System.Drawing.Point($bmp.Width, ($bmp.Height + 1)) $textBoxY.Location = New-Object System.Drawing.Point($bmp.Width, ($bmp.Height + 2)) $textBoxDisplay.Location = New-Object System.Drawing.Point($bmp.Width, ($bmp.Height + 3)) $mainBalloon = New-Object System.Windows.Forms.ToolTip $mainBalloon.IsBalloon = $true $mainBalloon.ShowAlways = $true $pointDragStart = New-Object System.Drawing.Point(0, 0) $formMain.Add_MouseDown({ Param($sender, $event) if ($event.Button -eq [System.Windows.Forms.MouseButtons]::Left) { $pointDragStart = New-Object System.Drawing.Point($event.X, $event.Y) } }) $formMain.Add_MouseMove({ Param($sender, $event) if($event.Button -eq [System.Windows.Forms.MouseButtons]::Left) { $formMain.Left += $event.X - $pointDragStart.X $formMain.Top += $event.Y - $pointDragStart.Y } }) $funcTextChange = { Param($sender, $event) if($textBoxCmd.Text -eq "exit") { $formMain.Close() } elseif([string]::IsNullOrEmpty($textBoxCmd.Text)) { $mainBalloon.Hide($formMain) } else { $x = 0; $y = 0; $display = 0 if(![int]::TryParse($textBoxX.Text, [ref]$x)) { $x = $formMain.Width / 2 } if(![int]::TryParse($textBoxY.Text, [ref]$y)) { $y = $formMain.Height / 2 } if(![int]::TryParse($textBoxDisplay.Text, [ref]$display)) { $display = 0 } if($display -gt 0) { $mainBalloon.Show($textBoxCmd.Text, $formMain, $x, $y, $display) } else { $mainBalloon.Show($textBoxCmd.Text, $formMain, $x, $y) } } } $textBoxCmd.Add_TextChanged($funcTextChange) $textBoxX.Add_TextChanged($funcTextChange) $textBoxY.Add_TextChanged($funcTextChange) $textBoxDisplay.Add_TextChanged($funcTextChange) $formMain.Controls.Add($textBoxCmd) $formMain.Controls.Add($textBoxX) $formMain.Controls.Add($textBoxY) $formMain.Controls.Add($textBoxDisplay) $formMain.ShowDialog() $mainBalloon.Dispose() $formMain.Dispose() ENDTEXTBLOCK FUNCTION Start(bmpPath, x=0, y=0, formName=EMPTY) IF formName=EMPTY THEN formName = "NotifyIcon form " + GET_UWSC_NAME POWERSHELL(REPLACE(REPLACE(REPLACE(REPLACE(_script, "$$formName$$", formName), "$$bmpPath$$", bmpPath), "$$x$$", x), "$$y$$", y), TRUE) RESULT = GETID(formName, , -1) FEND PROCEDURE SetMsg(id, msg=EMPTY, display=EMPTY, x=EMPTY, y=EMPTY) SENDSTR(id, msg, 1, TRUE) IF display <> EMPTY THEN SENDSTR(id, display, 4, TRUE) IF x <> EMPTY THEN SENDSTR(id, x, 2, TRUE) IF y <> EMPTY THEN SENDSTR(id, y, 3, TRUE) FEND ENDMODULE
SetMsgの引数は、サンプルだと第二引数のmsgまでしか利用していませんが、さらにdisplay,x,yがあります。
msg:表示メッセージ。長さ0もしくはEMPTYにすると吹き出しを消す。
display: 表示時間(msec)。この時間が経過すると自動的に消せる。省略および0の場合、自動的には消さない
x:画像からの吹き出し相対位置。省略時は真ん中あたり
y:画像からの吹き出し相対位置。省略時は真ん中あたり
そんなとこだね。