スキップしてメイン コンテンツに移動

第14回北海道開発オフに行ってきた

最初に第15回北海道開発オフのお知らせ。
日時 / DATE : 2010/02/20 09:30 to 17:00
定員 / LIMIT : 18 人
会場 / PLACE : 札幌市産業振興センター セミナールーム5(技能訓練棟3F) (札幌市白石区東札幌5条1丁目1-1)
http://atnd.org/events/3063
2010年最初の開発オフだ。そんな開発オフの第14回目が2009/12/26に開催された。もう2010年2月だけどかまわずレポート。
今回も前回に続いて強制シャットダウンアプリを開発。今回新しくWindows7ノートPCを買ったのでVisual Studio Express Editionを使用して開発ができる。
前回作成したメインフォームではラベルをひとつ置いて、残り秒数を表示するつもりだったが、ちょっと味気ないと思っていたので、事前準備として秒数表示に利用できる画像を探した。ちょうどブログDeveloper @ ADJUSTライトニングトークタイマーを公開されていたので画像をいただいて使ってみた。カッコヨイ。でもちょっと小さい。ライトニングトークタイマーなので当然か。しかたないのでPaint.NETを使って人気海外ドラマ風な画像を作ってみた。

開発オフ当日は、この画像を基に指定された数値に該当する部分のみのImageを取得するメソッドを用意して、そのメソッドを利用して指定されたDateTimeの値を表示するコントロールを作成するところからはじめた。

''' <summary> ''' デジタル時計風表示のコントロール ''' </summary> Public Class DigitalClock Private Const OneNumWidth As Integer = 80 Private Const OneNumHeight As Integer = 120 Private Const SeparaterWidth As Integer = 40 Private _date As Date Public Sub New() InitializeComponent() Me.DoubleBuffered = True End Sub ''' <summary> ''' 表示する時間を取得・設定する ''' </summary> Public Property Value() As Date Get Return _date End Get Set(ByVal value As Date) _date = value End Set End Property ''' <summary> ''' Paintイベントを発生させる ''' </summary> Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) MyBase.OnPaint(e) Dim x As Integer = 0 '分 Dim minutString As String = _date.Minute.ToString("00") Using img As Image = GetNumberImage(Integer.Parse(minutString.Chars(0))) e.Graphics.DrawImage(img, x, 0) End Using x += OneNumWidth Using img As Image = GetNumberImage(Integer.Parse(minutString.Chars(1))) e.Graphics.DrawImage(img, x, 0) End Using x += OneNumWidth '区切り Using img As Image = My.Resources.sep e.Graphics.DrawImage(img, x, 0) End Using x += SeparaterWidth '秒 Dim secondString As String = _date.Second.ToString("00") Using img As Image = GetNumberImage(Integer.Parse(secondString.Chars(0))) e.Graphics.DrawImage(img, x, 0) End Using x += OneNumWidth Using img As Image = GetNumberImage(Integer.Parse(secondString.Chars(1))) e.Graphics.DrawImage(img, x, 0) End Using x += OneNumWidth End Sub ''' <summary> ''' 指定数値のImageひとつを取得 ''' <summary> ''' <param name="number">
取得するImageの数値</param> Private Function GetNumberImage(ByVal number As Integer) As System.Drawing.Image Using nums As Bitmap = My.Resources.numbers Dim recF As RectangleF = nums.GetBounds(System.Drawing.GraphicsUnit.Pixel) recF.Width = OneNumWidth recF.X = number * OneNumWidth Return nums.Clone(recF, Imaging.PixelFormat.Format24bppRgb) End Using End Function End Class
また、カウントダウンクラスにTimeUpイベントを追加。残り時間が0になったら発生させる。

Public Class CountDown Private _period As Integer Private _remaind As Integer Private _timer As Timer ''' <summary> ''' コンストラクタ ''' </summary> '''
<param name="period">タイマの間隔</param> ''' <param name="remaind">タイマの残り時間</param> Public Sub New(ByVal period As Integer, ByVal remaind As Integer) Dim callback As New TimerCallback(AddressOf TimerCallback) _timer = New Timer(callback, Nothing, Timeout.Infinite, period) _period = period _remaind = remaind End Sub
''' <summary> ''' カウントダウンを開始する ''' </summary> Public Sub Start() _timer.Change(0, _period) End Sub
''' <summary> ''' カウントダウンする ''' </summary> ''' <param name="state"></param> Private Sub TimerCallback(ByVal state As Object) _remaind -= Me._period If _remaind >= 0 Then '残り時間あり OnTick(New TickEventArgs(_remaind)) Else '残り時間なし OnTimeUp(New System.EventArgs()) End If End Sub
''' <summary> ''' Tickイベントを発生させる ''' </summary> Protected Sub OnTick(ByVal e As TickEventArgs) RaiseEvent Tick(Me, e) End Sub
''' <summary> ''' TimeUpイベントを発生させる ''' </summary> Protected Sub OnTimeUp(ByVal e As System.EventArgs) RaiseEvent TimeUp(Me, e) End Sub
''' <summary> ''' 指定のタイマ間隔が経過したときに発生 ''' </summary> Public Event Tick(ByVal sender As Object, ByVal e As TickEventArgs) Public Event TimeUp(ByVal sender As Object, ByVal e As System.EventArgs) End Class
これで必要なクラスはそろった。これらのクラスを以下の作戦でシャットダウンアプリを完成させる。
  1. カウントダウンクラスのオブジェクトを作成
  2. TickイベントとTimeUpイベントのハンドラを追加してカウントダウンスタート
  3. メインフォームをダイアログ表示
  4. Tickイベントハンドラではイベントデータの残り時間をフォームに渡す
  5. TimeUpイベントハンドラではメインフォームを閉じる
  6. メインフォームが閉じたらシャットダウンを実行
なんとか開発オフ中に実装することができたので、成果発表にもお見せすることができた。成果発表の時にも話したが、カウントダウンする秒数は設定ファイルで指定することができるようにした。5分に設定すればライトニングトークタイマーとしても使えると思う。
完成したものを公開したいが、公開場所などを整えてからにする。

コメント

このブログの人気の投稿

VirtualBoxのUbuntu 18.04でNAT + ホストオンリーアダプター

VirtualBoxのVMにインストールしたUbuntu Server 18.04で、ネットワーク割当を「NAT」+「ホストオンリーアダプター」にする場合の設定についてメモ。 VMを作るとき、ゲストOSからインターネットに繋がって、かつホスト-ゲスト間でもつながる環境にしたいとき、VMのネットワーク割当は手っ取り早いのは「ブリッジアダプター」なんだけど、会社のネットワークでは都合がわるかったりするので「NAT」+「ホストオンリーアダプター」にしている。 アダプター1は「NAT」を選択 アダプター2は「ホストオンリーアダプター」を選択 ゲストOSであるUbuntuのネットワーク設定は、NATに該当するNICはDHPCで、ホストオンリーアダプターに該当するNICは固定IPとする。 Ubuntu 18.04ではネットワーク設定はNetplanで行う(Ubuntu 17.10から変わったようだ)。編集する設定ファイルは「/etc/netplan/50-cloud-init.yaml」 network: ethernets: {NATのNIC}: addresses: [] dhcp4: true optional: true {ホストオンリーアダプターのNIC}: addresses: [{固定IPアドレス}] dhcp4: no version: 2 ポイントは、ホストオンリーアダプターに該当するNICの固定アドレスを設定するときに、 ゲートウェイを設定しない こと。 以前に QiitaのVirtualBoxでNAT + Host-Only Network環境を構築する を参考にしていたのに、今回18.04で設定する際にすっかり忘れてはまってしまった。 IPアドレスは「192.168.0.2/24」のようにサブネットマスクも指定する。 NICに指定するデバイス名は以下コマンドで表示されるlogical nameが該当する。 > lshw -class network たいていは「enp0s3」「enp0s8」となるようだ。 設定ファイルを保存したら

画像を切り取って保存する

画像処理において、画像の一部を切り出すことをトリミングというらしい。画像編集ソフトなんかにも大抵「トリミング」機能が実装されているだろう。 そんな画像を切り取る処理を.NETでやってみる。 .NETでは画像を扱う際にはBitmapクラスを使用する。BitmapクラスのCloneメソッドでサイズを指定すれば、そのサイズのBitmapオブジェクトができるので、それを保存すればよい。Cloneメソッドの引数はRectangle構造体とPixelFormat列挙体。 Rectangle構造体とは四角形の位置とサイズを表したもの。元画像の左上を(0, 0)として(X座標, Y座標, 幅, 高さ)の値でRectangle構造体を作成して渡す。PixelFormat列挙体はヘルプを見てもよくわからなかった。とりあえずは元画像の値をそのまま渡す。 例えば photo by tsukacyi のようなユッケの画像をトリミングするプログラムは以下のように書ける '元画像 Dim source As Bitmap source = New Bitmap("source.jpg") '切り取るサイズ Dim rect As Rectangle rect = New Rectangle(30, 80, 400, 320) '切り取り後の画像 Dim trimed As Bitmap trimed = source.Clone(rect, source.PixelFormat) '保存 trimed.Save("trimed.jpg") source.Dispose() trimed.Dispose() トリミング後の画像は以下の通り。

Microsoft.VisualBasic.dllを参照しない(その1)

VB.NETには、VB6に実装されていたCIntなどの型変換関数やLeft、Rightなどの文字列関数が使用できる。これらはMicrosoft.VisualBasic名前空間で定義されている。 個人的にはこれらはVB6との互換性の為に用意されたものと考えていて、あまり使用しないようにしている。名前付けのガイドラインにも沿っていないため、他の.NETなメソッドと並ぶと違和感があるというのもある。 注意:このエントリはVisual Basic 2005 Express Editionと.NET Framework2.0 SDK環境を元に書いています。 そんなわけでチーム開発の場合に、これら関数を使用しないよう、Microdoft.VisualBasic.dllを参照しないプロジェクトを作成しようと考えた。 Visual Studioのプロジェクトのプロパティから「参照」タブを開いてみると、すでに参照しているdllにMicrosoft.VisualBasic.dllが含まれていない。  下の一覧にImportされる名前空間が表示されているが、そこには含まれている。 Importされる名前空間からチェックをはずし以下のソースを書いてみる Public Class VisualBasicTest Public Shared Sub Main() Dim i As Integer = CInt("1991") System.Console.WriteLine(i) End Sub End Class だが、ビルドは通って実行もできてしまう。 逆アセンブリしてみる。 スタートメニューから「Microsoft .NET Framework SDK v2.0」→「Tools」→「MSIL 逆アセンブラ」を起動して、ビルドでできているexeを開く。すると、MANIFESTの部分を見てみると下記記述が見つかる。参照しているようだ。 .assembly extern Microsoft.VisualBasic { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) .ver 8:0:0:0 } きっとVisual Studioが