2009年6月24日水曜日

VC++ デバイスコンテキストを使っての描画方法。 ( GetDC、CreateSolidBrush、SelectObject、PatBlt、使い方 )

デバイスコンテキストについて

業務にて、デバイスコンテキストを使っての描画処理を担当。
描画関係の知識がなかったのでちょろっと勉強してみたので、メモを残しておく(たいしたことないけど 笑)。

Ⅰ. デバイスコンテキストとは

ウィンドウの描画に必要な材料のパッケージ。よく画用紙と画材のセットと表現される。
文字を書いたり、背景の色を変えたり、線を引いたり、画像を表示させたり・・・
といった全ての操作はこいつ(デバイスコンテキスト)のハンドルを取得するところから始まる。

業務系アプリでは、画面のほぼ全てが MFC 標準のコントロールで事足りてしまうのであまり関わる機会がない。
が、色の変更などの細かい制御をするときは世話になるので、覚えておくと非常に便利だ。

Ⅱ. 画用紙と画材のセット・・・というと?

デバイスコンテキストが画用紙と画材のセットと表現される理由は何か。
それは、デバイスコンテキストが持っているオブジェクトを知れば納得がいく。
以下がデバイスコンテキストが持つオブジェクト・・・つまり画材のリスト ( 厳密にはこれだけではない )

  • Bitmap ・・・ 画像(画像を表示するときに使う)
  • Brush  ・・・ ブラシ(背景を塗りつぶすときに使う)
  • Font   ・・・ フォント(文字を書くときに使う)
  • Pen     ・・・ ペン(線を引くときに使う)
  • Region   ・・・ 領域(描画領域を限定するときに使う)

デバイスコンテキストは、これらの画材を全種類持っている。
ただし、もてる画材は1種類につき1つで、Pen なら Pen 1個。
つまり、赤ペンに青ペンに緑も・・のように、同じ種類の画材は複数持てないので入れ替えて使う。

また、1つのウィンドウにつき、デバイスコンテキストは1つである。
ということから、ウィンドウ、およびそれに張り付いている全てのコントロールもウィンドウなので、それぞれが1つづつデバイスコンテキストを持っていることになる。

[デバイスコンテキストのイメージ ( クリックで最大化 )]
無題

Ⅲ. デバイスコンテキストの使い方

Ⅱ まででデバイスコンテキスト(以下 DC )の考え方が理解できたとうことで、実際にコードを書いてみる。
まずは、DC のハンドルを取得してから描画をおこなう一連の流れはこうだ。

  1. DC のハンドルを取得
  2. 画材を作成
  3. 画材を設定
  4. 描画
  5. 画材を元に戻す
  6. 画材を削除
  7. DC のハンドルを開放

すでにお気づきだと思うが、これにはいくつか注意点がある。

  • DC のハンドルを取得したら、最後に必ず開放すること
  • 使う画材を作成したら、最後に必ず削除すること
  • 画材を入れ替えたら、最後にかならず元に戻すこと

以上の点に注意して、画面(画用紙)を赤で塗りつぶす処理を書くとこうなる。

--------------------------------------------------------------------------------
// ※ hWnd は、描画対象となるウィンドウのハンドル

//
// 画面を赤で塗りつぶす
//

// DC のハンドルを取得
HDC hDC = ::GetDC( hWnd );

// 赤のブラシを作成(画材を作成)
HGDIOBJ hBrushRed = ::CreateSolidBrush( RGB( 255, 0, 0 ) );

// 赤のブラシを設定(画材を設定)
HGDIOBJ hBrushOld = ::SelectObject( hDC, hBrushRed );

// 画面をぬりつぶす(描画)
RECT rtWindow;
::GetWindowRect( hWnd, &rtWindow );
::PatBlt( hDC, 0, 0, rtWindow.right, rtWindow.bottom, PATCOPY );

// 画材を元に戻す
::SelectObject( hDC, hBrushOld );

// 画材を削除
::DeleteObject( hBrushOld );

// DC のハンドルを開放
::ReleaseDC( hWnd, hDC );

--------------------------------------------------------------------------------

これで、画面を赤で塗りつぶすことができた。

やりたい描画、つまり使う画材によって呼び出す API が変わるが、
基本的な処理の流れは、どの画材を使うときも同じである。
( 逆に、それぐらいしか変わりがないとも言える )

Ⅳ. 最後に

今回は、GetDC を使って実装してみた。
GetDC は、ウィンドウハンドルのパラメータに NULL を設定すると、スクリーン全体の DC をも取得できる強力な API である。
画面のちょっとした描画にはもっと適した BeginPaint という API があるし、MFC のクラスを使うともっと簡単に実装できるので、
次回はそれらを使ったコードの書いてみることにする。

 

以上。

2009年6月3日水曜日

Visual Studio 2008 Team System 新機能の概要メモ

Visual Studio 2008 Team System 機能メモ
 
--------------------------
Ⅰ. コード分析
 A. 概要
  1. およそ200種類、大枠で11項目のルールからコードを検証する
  2. アンマネージコードのコード分析は貧弱
 B. 使い方
  1. プロジェクトのプロパティから、コード分析を有効にして、分析を実行する

Ⅱ. プロファイリング
 A. 概要
  1. CPU 負荷や、実行速度などのボトルネックの発見を助ける
  2. サンプリングは、定期スナップショットや、モジュール単位の検証など大まかな調査をする
  3. インストルメントは、関数ごとの処理などより詳細な情報を集める
  4. サンプリングは、長期シナリオにも向いている
 B. 使い方
  1. プロファイリングウィザードからプロジェクトを指定し、実行するだけ
------------------------------
 
 
調査が足りなすぎだけど、とりあえずメモ。
アンマネージ C++ で使えそうなのは、プロファイリングくらいかなぁ・・
カバレッジ機能とかは後日チェックしてみよう。
 
 
 
 
 

2009年5月20日水曜日

Visual Studio で、ソース管理プラグインの初期化エラーの対処法

本日の業務中、表題の件で1時間ほど時間を無駄にしてしまったので記録しておく。
・・・といっても、最終的に解決したのは自分じゃなくて先輩なのだけど・・(感謝
 

[問題]
Visual Studio 2008 で開発をはじめたところ、Visual SourceSafe(以下VSS)のバインドに失敗していることに気がついた。マシンには以前、Visual Studio6、.NET2003、2005、2008が入っており、2003と2005はアンインストールされた状態であった。Visual Studio 2008 上では、ソース管理プラグインの初期化エラーが発生しソース管理へのバイントに失敗する。そして、環境設定からもプラグインに SourceSafe を指定することができずに「なし」と表示されてしまう・・という状況。
ちなみに当然、VSS 6.0 はインストールされていた。。。
 
[解決]
コマンドプロンプトから、「RegSvr32 ssscc.dll」を実行する。
 
[原因]
どうやら、ssscc.dll が VSS のプラグインそのもので、通常はサービスに登録されているが、何かの拍子に(2003や2005のアンインストール時?)削除されてしまっていたようだ。
 
[補足]
あと、VS2008 からの VSS6 使用は公式サポートされていない。
また、VSS6 だと Unicode のソース管理に問題が発生する可能性がある様で、2005を使うのがベストらしい。

 
以上。
 
 
 

2009年2月24日火曜日

Adobe Flash Player の高速化(軽量化)!最新版の Flash は重い・・。

SONY PCG-U3 でのできごと。
 
Flash Player を最新にしてください・・・の指示に従いアップデートをしたら、
今までカクつきながらもなんとか再生できていた、youtube、Gyao などが完全に紙芝居になった。
 
なんとか古い Flash Player ( Ver.7 ) をインストールしなおしたら、再び動くようになった。
ちなみに、Ver.7 以前のバージョンは、古すぎで再生不可だった。
・・・最近の最新版はいろいろ余計なものを積みすぎていてけしからん。
 
過去のバージョンは、以下から入手可能。
アンインストーラを走らせて、インストールするだけ。
 
※導入は自己責任でね
 
テスト用のアーカイブ版 Flash Player の提供について

2009年1月5日月曜日

Excel ファイルの全シートを、左上選択状態にする ( VBA )

Excel を使っていて、いつもストレスを感じることがある。
それは、データを「保存」すると、開いていたシート、スクロールの位置まで保存されてしまうということ。。
 
”ここを編集していました”っていう備忘には便利かもしれないけど、ネットワークで共有しているファイルなど、
複数人が編集するファイルの場合は、開く度にシートがごちゃごちゃになっていて、非常に作業の効率が悪い。
 
ということで、几帳面というより少し神経質な人のために(自分)、
全てのシートを左上選択状態(A1セル)にするマクロを作成した爆笑
 
★こんな場面で意外と便利だ。
 1.ショートカットに設定して、毎回保存する前に整える
 2.ファイルオープンのイベントに追加して、表示位置をリセットして開く
 
以下コード
'
' 全てのシートを左上選択状態にする
'

Sub SelectA1AllSheets()
' 全シート分実行
Dim i As Integer
For i = 1 To Worksheets.Count
' シートをアクティブ化
Worksheets(i).Activate
' 左上にスクロール
Dim j As Integer
For j = 1 To Windows(1).Panes.Count
Windows(1).Panes(j).ScrollColumn = 1
Windows(1).Panes(j).ScrollRow = 1
Next
' 左上を選択
ActiveSheet.Cells(1,1).Select
Next
' 1番目のシートをアクティブ化
Worksheets(1).Activate
End Sub

※注意

 ・ウィンドウ枠の固定、ウィンドウの分割にも対応している

 ・念のため、編集しているファイルではなく個人用マクロブックに登録するのを忘れずに

 

以上

 

 

2008年12月28日日曜日

コメントアウトマクロ、VisualStudio6.0 ( VS6 )

VS6には、複数行をまとめてコメントアウトする機能が用意されていない。
VS2003以降にはあって、これがなれると結構便利。
 
なので、VS6でも使いたい・・・と思い作ってみた。
---------------------------
Sub Comment ()
  ' Check a type of the active window
  Dim win
  Set win = ActiveWindow
    If win.type <> "Text" Then
      Exit Sub
    End If
 
  Dim CommentPos
  Dim CommentStr
  Dim StartRow
  Dim StopRow
  CommentPos = 0
  CommentStr = "//" ' Symbol of the comment
  StartRow = ActiveDocument.Selection.TopLine
  StopRow = ActiveDocument.Selection.BottomLine
  ' Get position to insert the symbol.
  For i = StartRow To StopRow
    ActiveDocument.Selection.GoToLine i
    ActiveDocument.Selection.SelectLine
    orgLen = Len( ActiveDocument.Selection )
    trmLen = Len( ActiveDocument.Selection )
    If CommentPos < ( orglen - trmLen ) Then
      CommentPos = orgLen - trmLen
    End If
  Next
 
  ' Add string of the symbol of comments to top of lines.
  For i = StartRow To StopRow
    ActiveDocument.Selection.GoToLine i
    ActiveDocument.Selection.SelectLine
        selLine = ActiveDocument.Selection
        fstHalf = Mid( selLine, 1, CommentPos )
        lstHalf = Mid( selLine, CommentPos + 1, Len( selLine ) - CommentPos + 1 )
        ActiveDocument.Selection = fstHalf + CommentStr + lstHalf
  Next
End Sub
---------------------------
2点注意
・コメント外しには対応していない
・コメント文字がコードの先頭でなく、行の先頭に来てしまうかも
・わけあって印刷したコードを手で打ち込んだので入力ミスがあるかも
 
以上。
 
Borland であったコード補完機能?を作ったら便利そうだなあ。
 
 

2008年10月23日木曜日

クラスのメンバをヘッダで初期化する

ますます C++ の忘れっぷりを痛感している今日この頃。
基礎だけど重要なことも飛んだりしている。例のごとくメモ。
定数には「#define」がよく使われているが、
あるクラス自体の定数など、内部でしか使わないものはそのクラスのメンバ変数にしておきたい。
ただ、コンストラクタとかメンバイニシャライザで初期化するのって面倒臭いし、
何よりもコードが読みにくいので出来る限りヘッダで初期化しておきたい。
・・・そんな時は以下!
 
-----------------
class Human{
private:
  // int 範囲の場合は enum で対処可能
  enum {
    m_eLegCount = 2,
    m_eArmCount = 2,
    m_eFingerCount = 5
  };
}
-----------------

int の範囲ならこれで。
ただ、文字列や配列もやりたい。
その場合はヘッダ ( .h ) では無理なので実装部 ( .cpp ) で初期化する。
 
-----------------
// .h file とする
class Human{
private:
  // ここで初期化したメンバは以下の宣言で使える
  enum {
    m_eMaxNameCount = 50
  }
  // メンバ定数分の配列を確保している
  // static の場合は外部で初期化できる
  static const char szName[m_eMaxNameCount];
}
// .cpp file とする
const char Human::szName = "Suzuki Ichiro";
-----------------

static なら、private でも外部で初期化できる。
また、ここで static の表記は不要。
 
以上。