2008年2月25日月曜日

DataGridViewのTabStop対応(3)

前回の続きでTabStop制御について。
前回で「何をもってフォーカス可能と判断するか」というのを決めたので、次にやることへ。

  • 次にフォーカス可能なセルはどこか、を調査する

というのが次に行う処理。具体的には2方向に分かれることになる。

  • 現在のカレントセルより後ろに存在するセルでフォーカス可能か
  • 現在のカレントセルより前に存在するセルでフォーカス可能か

まぁこれは当たり前なところで、実際には「前か後ろか」の違いがあるだけ。やることは同じ。
そしてここで注意するのは「次ってどっち?」というところ。
画面の仕様にも関連するけれども、次というのが、「右方向」な場合と「下方向」な場合があるよね。
まぁこれはとりあえず右方向用メソッドと、下方向用メソッドで切り分けておいていいと思う。
後々リファクタリングの段階で、くっつけたりまぜたり分解したりしてしまえばいいかな、と。

''' <summary>同じ行の中で次にフォーカス可能なセルを取得する</summary>
Private Function GetAfterCellCanFocusInRow() As System.Windows.Forms.DataGridViewCell

  If Me.CurrentCell Is Nothing Then Return Nothing

  Dim checkResult As System.Windows.Forms.DataGridViewCell = Nothing
  Dim owningCellIndex As Integer = Me.CurrentRow.Cells.IndexOf(Me.CurrentCell)
  For Each gridCell As System.Windows.Forms.DataGridViewCell In Me.CurrentRow.Cells
    If Not Me.CheckFocusCell(gridCell) Then Continue For

    Dim targetCellIndex As Integer = Me.CurrentRow.Cells.IndexOf(gridCell)
    If owningCellIndex >= targetCellIndex Then Continue For
    checkResult = gridCell
    Exit For
  Next
  Return checkResult

End Function

やろうとするとこんな感じかな?これはサンプルとして「右方向」に走査するメソッドなので、コレを元にして下方向や左方向を操作するメソッドを用意してあげればいいと思う。そこまでできれば、後はProcess系メソッドのオーバーライドへといけるね。

2008年2月22日金曜日

DataGridViewのTabStop対応 (2)

まずTabStop対応を行うに当たって、決めておかないといけないのが。

  • 何を持ってフォーカス可能と判断するか

という点。簡単に言えば「入力可能か?」ということに落ち着きそうなんだけど、それを色々なプロパティを元に判断してあげる必要があるんだよね。今回は(手軽にw)こういう条件で。

  1. ReadOnly=False:読み取り専用でない
  2. Visible=True:表示されている

それだけの判断で対応したいと思う。実際に業務とかで利用するには、もう少し条件がいるとは思うけどね。
読み取り専用であってもフォーカスさせたいとか、そういうケースはあるだろうから。
まぁ、そのあたりの制御をプロパティなりを通して設定できるように設計するのがベターだと。

なのでまずは、あるセルがこの条件を満たすか、というメソッドを用意してあげよう。

''' <summary>セルがフォーカス可能かをチェックする</summary>
''' <param name="targetCell">対象となるセル</param>
''' <returns>フォーカス可能な際はTrue</returns>
Protected Overridable Overloads Function CheckFocusCell( _
  ByVal targetCell As System.Windows.Forms.DataGridViewCell) As Boolean

  If (Not targetCell.ReadOnly) AndAlso (targetCell.Visible) Then Return True
  Return False

End Function

ざっくり用意するとこんな感じ。これでまずは「フォーカス可能なセルか」という判断ができるようになった。
あとは、次にフォーカス可能なセル、というのを検索する際にこのメソッドをバシバシ利用してあげればいいというハナシ。
その際にどういう処理になるか、ってのは次の記事で。

Office Live SmallBusiness

5ユーザーまでなら無償で利用可能なOfficeLiveスイート。
中身は簡単に言えばSharePointで、LiveIDさえあれば無料で利用することが可能。

簡単なCMSやグループウェア、プロジェクト管理などができてしまううえに、メールアドレスも新規に取得できて、なおかつweb上で利用可能な様にアドレスまでくれてしまうという太っ腹。

マジメにこういうのが無償ででまわってくると、商売の仕方や仕事の仕方ってのは考え直さないといけない気がする・・・。

2008年2月20日水曜日

DataGridViewでのTabStop対応

これもけっこうみかけるサンプルとして、セルを拡張してTabStopを有効化しよう、というのがあるよね。
でも個人的にはこの方針はあまり好きじゃなかったりする。

というのも、セルを拡張して対応するとそのセル以外では利用できなくなるからなんだよね。
普通にDataGridViewTextCellとか利用しても、TabStopが有効にならないから。

なので個人的には、セル拡張もアリだけどDataGridView本体の拡張も行うべきだと思ってる。
実際の対応内容は次回以降だけど、基本方針だけを。

  • ProcessDialogKey関連のメソッドオーバーライドにて対応
  • TabStop=Falseとなる条件を決めておきそれによって判断
  • ただし、あらかじめ拡張したセルを使う前提ならばそれを優先する

こんなところかな。次回から少しずつこのネタで引っ張る予定w

MS08-008:OLEオートメーションの脆弱性

マイクロソフト セキュリティ情報 MS08-008 - 緊急 : OLE オートメーションの脆弱性により、リモートでコードが実行される (947890)

まぁ今回に限らずよくあることなんだけど。基本的にセキュリティパッチは「それを配布したヤツが責任もって再配布しろ」が基本スタンスですわね。

さて。

このアドバイザリにて対象となっているのはOLEAUT32.dll。そしてVisualBasic6にて開発されたもの、という限定つきだ(Ver6世代の言語で唯一影響を受ける)。つまるところ、VBの場合AP配布の際に上書きして旧バージョン使いやがることが多いから責任持つのはAP製作者側だぞ、ということ。

確かデストリビューションウィザード使うと、再配布可能なものは強制的に再配布してしまってたんじゃなかったけかな?なので対応としては、oleaut32.dllを利用するAPを再コンパイルしてインストーラの再構築ですなぁ。VisualInterDevでWindowsInstallerを利用したときは、まだ判断してくれていたと思うけどどうだったかな?

こういったところにどれだけの人が注意しているんだかねぇ。

2008年2月18日月曜日

コンソールセッションへのリモートデスクトップ

今まで(~Vista)だと、mstsc.exeのオプションで、/consoleをつけてあげるかrdpファイルの中身にコンソールセッションを表す記述をしてあげればOKだったのが。

VistaSP1およびWindows2008Server
から変更になります。2008Serverはアナウンスがあったようだけど、VistaSP1については何も聞いていなかったのでメモメモ。

mstsc.exe /admin

これでコンソールセッションに接続するそうだ。
ただコンソールセッションといっても、いままでみたいにセッション0ではないのは周知の通り・・・。

2008年2月9日土曜日

VS2005とVS2008の間でのプロジェクトファイル・・・

色々なところで
一度アップグレードしたprojファイルは、旧バージョンでは使えなくなるよー
と聞いていたんだけど。

試しにライブラリ用のプロジェクトをコンバートしてみて、そのちょろっと変更したあとで保存。その後VS2005で読み直してみたんだけど。

・・・読めちゃった
エラーも出てません。アルェー?

一応双方のprojファイルでdiffとってみると、変更があったところはほとんどなかったのよね。
プロダクトバージョンとか、ターゲットFrameWorkとかが増えて、あとは発行回りがprojファイルに保存されているなぁ、ってのが見えたくらい。

ひょっとして会社には内緒で、自分ひとりだけVS2008環境にしてやっていてもイケる?w

VirusBuster2008が・・・

ウィルスバスター2008が反応します - MSDN フォーラム

どうやらオートコンプリートを利用しているTextBoxがあると、バスター2008が誤って反応してしまうそうで。
・・・今のところバスターだけっぽいのが救いだw

というか、最近のトレンドマイクロは一時期に迫る勢いで色々問題でてきているような気がするなぁ。

2008年2月8日金曜日

まぁ、そうだわな

マイクロソフト製品 & テクノロジのここが聞きたい ~人気講師がお答えします~

Visual Studio 2005 で開発するか、2008 で開発をするか迷っています。Visual Studio 2008 で開発する際のメリットはなんでしょうか? またデメリットはありませんか?

と言う質問に対して、NECグループにいるMVPforVBな人が答えているんだけど。

最後にデメリットですが、基本的にありません。ひとつだけあるとすると、2008 による開発があまりに快適なので、2 度と 2005 には戻ることができないということくらいでしょうか。

・・・今からでも2008に切り替えたいんですがどうでしょうかw

2008年2月5日火曜日

.Net Frameworkのソース・・・

以前にも書いたことのある話題で、.NetFrameWorkのソースを公開するってんがあったんだよね。いくらリバースできるとはいえ、ちゃんとしたソースの形で提供されるほうがうれしいので結構心待ちにしていたんだけど・・・。

VisualStudio2008(Std以上)でないとできませぬ。
(´・ω・`)

どうやらソースを参照する機能として「外部サーバー」を設定できるようになっているのがStd以上だということで、Expではダメだそうです。

まぁ普通に考えると、仕事で使うんだから最低でもStdだろJK・・・というところなんだろうけど。Expは軽いから好きなんだけどなぁ。

2008年2月4日月曜日

ロジックからCellの値を設定しても画面に反映しない?

たぶんDataGridViewを触りはじめでよくひっかかるであろう話題がコレ。
プログラムからは、DataGridView.Rows(Y).Cells(X).Value = "なにがし"とかやっているのに、
画面上では全く反映されていない、というヤツ。

これもわかってしまうと簡単で・・・。
今現在アクティブなのが編集コントロールだから
なんだよね。

つまるところ、セルの値は変更されているんだけど編集コントロール側の値が変更されていないので、画面上ではなにも変更されていないように見えるわけで。
んじゃあどうするか、と言われると・・・セルの値が変更された際は編集コントロールの値も変更させればOKなわけで。

If (Me.IsCurrentCellInEditMode) AndAlso _
   (e.RowIndex = Me.CurrentCell.RowIndex) AndAlso _
   (e.ColumnIndex = Me.CurrentCell.ColumnIndex) Then
    If Me.EditingControl IsNot Nothing Then
        With DirectCast(Me.EditingControl, System.Windows.Forms.IDataGridViewEditingControl)
            If Me.CurrentCell.Value IsNot Nothing Then
                .EditingControlFormattedValue = Me.CurrentCell.Value
            End If
        End With
    End If
End If

CellValueChangedイベントとか、OnCellValueChangedメソッドでこんな風にしてあると、どこかからCellの値を操作したタイミングで編集コントロール側の値(EditingControlFormattedValueプロパティ)を書き換えます。ただし、上のサンプルはまだまだ考慮しないといけない点が抜けているので、そのあたりは手を加える必要がありますねぇ。
Null(Nothing)だったらどうするか、とかそういった点は、あえて実装していないということで言い張っていますw

DataGridViewの行番号描写

これも色々とサンプルが見当たるものなので、ちょっと注意点を。

RowPostPaintイベントを利用して番号をAPIで直接描写、というのが一番ベターな方法になるのは間違いないところで。
というのも、これと似たような方法として、「RowHeaderCell.Valueに行番号となる値を設定する」方法もあるんだけど、これの場合は「最描写」を意識しないといけないため、ちょっと手間が増えるんだよね。

そしてもうひとつやってはいけないタイミングが存在していて。

RowPostPaintイベントやRowPrePaintイベントにてRowHeaderCell.Valueの値を操作すると、DataGridViewの動作が不安定になります。

というのがあるので、サンプル通り、RowPostPaintイベント(またはOnRowPostPaintメソッド)にてAPIにて番号描写、というのが一番ベターだったりします。

なんで不安定になるか、というところまでは調査していないですけどね。大体は描写しようとしているイベントの中で、その元ネタを操作するからだとは思います・・・。

2008年2月1日金曜日

DataGridViewTextBoxEditingControl系統でオートコンプリート

よくあるネタとして、なんだけどひとつだけ注意点があったので書いておこうかと。

オートコンプリート系のプロパティを開放するようにCell、Columnを継承して拡張するというのは、簡単にできると思う。
ネット上でもIMEModeが設定できるように~とか、その類とやることは同じ。なのでAutoCompleteMode、AutoCompleteSource、AutoCompleteCustomSourceプロパティをそれぞれ開放してあげるだけで、下ごしらえとしてはOKだね。

注意しないといけないのは、そのプロパティをセットするタイミングで。

Enterイベント系(今回はOnEnterメソッド内)でこれらのプロパティをいじくると。
Win32Exceptionが発生します。

MSDNとか調べたんだけど、このあたりについてはどうも記述がのっていなかったんだよねぇ・・・。
まぁ理由はわからずともそうなってしまうので(w)、メソッドの本来の目的通りCellクラスのInitializeEditingControlメソッドで設定してあげるのが一番いいんじゃないかな?