DoboWiki
Top
> .NETプログラミング研究/34 をテンプレートにして作成
.NETプログラミング研究/34 をテンプレートにして作成
開始行:
#title(.NETプログラミング研究 第34号)
#navi(.NETプログラミング研究)
#contents
*.NETプログラミング研究 第34号 [#d6888b5d]
**お知らせ [#k62d31be]
過去に発行した「.NETプログラミング研究」のタイトルの一覧...
-[[.NETプログラミング研究 バックナンバー>https://dobon.ne...
バックナンバーのメニュー部分を切り出して列挙して表示して...
**.NET質問箱 [#h26a52f5]
「.NET質問箱」では、「どぼん!のプログラミング掲示板」に...
-[[どぼん!のプログラミング掲示板>https://dobon.net/vb/bb...
***文字列の計算式の計算結果を取得するには? [#d2a14585]
#column(注意){{
この記事の最新版は「[[文字列の計算式の計算結果を取得する>...
}}
''【質問】''
例えば、"(1+6)*5/(7-4)"のような計算式を表す文字列から、そ...
''【回答】''
これには、いろいろな方法が考えられます。
正攻法で行けば、計算式を解析し、計算するコードを自分で書...
-[[A Math Expression Evaluator>http://www.codeproject.com...
さらに、掲示板でArAyさんが紹介されたMSDN Japanの「アルゴ...
-[[アルゴリズム入門:第1章 Visual C# による文字列処理入門>...
このように自分でコードを書く以外の方法も様々あります。
まず、JScript.NETのEvalを使う方法があります。この方法は、...
-[[GotDotNet Message Boards - String to Numeric>http://ww...
この方法によると、まず参照に「Microsoft.Jscript」と「Micr...
#code(vbnet){{
'計算式
Dim exp As String = "(1+6)*5/(7-4)"
Dim ve As Microsoft.JScript.Vsa.VsaEngine = _
Microsoft.JScript.Vsa.VsaEngine.CreateEngine()
Dim result As Double = _
CDbl(Microsoft.JScript.Eval.JScriptEvaluate(exp, ve))
'結果を表示
Console.WriteLine(result)
}}
#code(csharp){{
//計算式
string exp = "(1+6)*5/(7-4)";
Microsoft.JScript.Vsa.VsaEngine ve =
Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
double result =
(double) Microsoft.JScript.Eval.JScriptEvaluate(
exp, ve);
//結果を表示
Console.WriteLine(result);
}}
また、JScriptCodeProviderにより、Evalメソッドを実行する方...
-[[An Eval Function for C# using JScript.NET (JavaScript)...
この方法によると、次のようなコードがかけます。
#code(vbnet){{
'Imports System.Reflection
'Imports System.CodeDom.Compiler
'が宣言されているものとする
'計算式
Dim exp As String = "(1+6)*5/(7-4)"
'計算するためのコード
Dim [source] As String = _
"package Evaluator {" + vbCrLf + _
"class Evaluator {" + vbCrLf + _
"public function Eval(expr : String) : String {" + vb...
"return eval(expr);} } }"
'コンパイルするための準備
Dim cp = New Microsoft.JScript.JScriptCodeProvider
Dim icc As ICodeCompiler = cp.CreateCompiler()
Dim cps As New CompilerParameters
Dim cres As CompilerResults
'メモリ内で出力を生成する
cps.GenerateInMemory = True
'コンパイルする
cres = icc.CompileAssemblyFromSource(cps, [source])
'コンパイルしたアセンブリを取得
Dim asm As [Assembly] = cres.CompiledAssembly
'クラスのTypeを取得
Dim t As Type = asm.GetType("Evaluator.Evaluator")
'インスタンスの作成
Dim eval As Object = Activator.CreateInstance(t)
'Evalメソッドを実行し、結果を取得
Dim result As String = CStr(t.InvokeMember("Eval", _
BindingFlags.InvokeMethod, Nothing, eval, New Object(...
'結果を表示
Console.WriteLine(result)
}}
#code(csharp){{
//using System.Reflection;
//using System.CodeDom.Compiler;
//が宣言されているものとする
//計算式
string exp = "(1+6)*5/(7-4)";
//計算するためのコード
string source =
@"package Evaluator
{
class Evaluator
{
public function Eval(expr : String) : String
{
return eval(expr);
}
}
}";
//コンパイルするための準備
CodeDomProvider cp = new Microsoft.JScript.JScriptCodePro...
ICodeCompiler icc = cp.CreateCompiler();
CompilerParameters cps = new CompilerParameters();
CompilerResults cres;
//メモリ内で出力を生成する
cps.GenerateInMemory = true;
//コンパイルする
cres = icc.CompileAssemblyFromSource(cps, source);
//コンパイルしたアセンブリを取得
Assembly asm = cres.CompiledAssembly;
//クラスのTypeを取得
Type t = asm.GetType("Evaluator.Evaluator");
//インスタンスの作成
object eval = Activator.CreateInstance(t);
//Evalメソッドを実行し、結果を取得
string result = (string) t.InvokeMember("Eval",
BindingFlags.InvokeMethod,
null,
eval,
new object[] {exp});
//結果を表示
Console.WriteLine(result);
}}
さらに、掲示板でピラルクさんが提案されたように、CSharpCod...
-[[Runtime Compilation (A .NET eval statement)>http://www...
-[[Evaluating Mathematical Expressions by Compiling C# Co...
具体的なコードは、例えば、次のようなものです。
#code(vbnet){{
'Imports System.Reflection
'Imports System.CodeDom.Compiler
'が宣言されているものとする
'計算するためのコード
Dim [source] As String = _
"public class MainClass {" + vbCrLf + _
"public static double EVal() {" + vbCrLf + _
"return (1d+6d)*5d/(7d-4d);" + vbCrLf + _
"} }"
'コンパイルするための準備
Dim cp = New Microsoft.CSharp.CSharpCodeProvider
Dim icc As ICodeCompiler = cp.CreateCompiler()
Dim cps As New CompilerParameters
Dim cres As CompilerResults
'メモリ内で出力を生成する
cps.GenerateInMemory = True
'コンパイルする
cres = icc.CompileAssemblyFromSource(cps, [source])
'コンパイルしたアセンブリを取得
Dim asm As [Assembly] = cres.CompiledAssembly
'MainClassクラスのTypeを取得
Dim t As Type = asm.GetType("MainClass")
'EValメソッドを実行し、結果を取得
Dim d As Double = CDbl(t.InvokeMember("EVal", _
BindingFlags.InvokeMethod, Nothing, Nothing, Nothing))
'結果を表示
Console.WriteLine(d)
}}
#code(csharp){{
//using System.CodeDom.Compiler;
//using System.Reflection;
//が宣言されているものとする
//計算するためのコード
string source = @"
public class MainClass
{
public static double EVal()
{
return (1d+6d)*5d/(7d-4d);
}
}";
//コンパイルするための準備
CodeDomProvider cp = new Microsoft.CSharp.CSharpCodeProvi...
ICodeCompiler icc = cp.CreateCompiler();
CompilerParameters cps = new CompilerParameters();
CompilerResults cres;
//メモリ内で出力を生成する
cps.GenerateInMemory = true;
//コンパイルする
cres = icc.CompileAssemblyFromSource(cps, source);
//コンパイルしたアセンブリを取得
Assembly asm = cres.CompiledAssembly;
//MainClassクラスのTypeを取得
Type t = asm.GetType("MainClass");
//EValメソッドを実行し、結果を取得
double d = (double) t.InvokeMember("EVal",
BindingFlags.InvokeMethod,
null,
null,
null);
//結果を表示
Console.WriteLine(d);
}}
前のJScriptCodeProviderを使った方法と比べると、この方法は...
(*1)この問題に関しては、次のページに詳しいです。
-[[Dynamically executing code in .Net>http://www.west-win...
Microsoft Script Controlが使用できるならば、VBScriptやJSC...
#code(vbnet){{
'計算式
Dim exp As String = "(1+6)*5/(7-4)"
Dim t As Type = _
Type.GetTypeFromProgID("MSScriptControl.ScriptControl")
Dim obj As Object = Activator.CreateInstance(t)
t.InvokeMember("Language", _
System.Reflection.BindingFlags.SetProperty, _
Nothing, _
obj, _
New Object() {"vbscript"})
'Eval関数で計算を実行して結果を取得
Dim result As Double = CDbl( _
t.InvokeMember("Eval", _
System.Reflection.BindingFlags.InvokeMethod, _
Nothing, _
obj, _
New Object() {exp}))
'結果を表示
Console.WriteLine(result)
}}
#code(csharp){{
//計算式
string exp = "(1+6)*5/(7-4)";
Type t = Type.GetTypeFromProgID("MSScriptControl.ScriptCo...
object obj = Activator.CreateInstance(t);
t.InvokeMember("Language",
System.Reflection.BindingFlags.SetProperty,
null,
obj,
new object[] {"vbscript"});
//Eval関数で計算を実行して結果を取得
double result = (double) t.InvokeMember("Eval",
System.Reflection.BindingFlags.InvokeMethod,
null,
obj,
new object[] {exp});
//結果を表示
Console.WriteLine(result);
}}
これ以外にも、DataTable.Computeメソッドを使う方法など、ま...
○この記事の基になった掲示板のスレッド
-[[C#で変数の中身を実行する: 投稿者(敬称略) ArAy, ピラル...
-[[文字列で表現した数式を計算: 投稿者(敬称略) nissa.com, ...
***TabControlのTabPageを非表示にするには? [#of915b3e]
#column(注意){{
この記事の最新版は「[[TabControlのTabPageを非表示にする>h...
}}
''【質問】''
TabControlのTabPageにはVisibleプロパティが見つかりません...
''【回答】''
TabPageを非表示にするには、TabControl.TabPagesプロパティ...
TabControlのTabPageを隠し、再び表示させるためのコードを以...
#code(vbnet){{
Public Class TabPageManager
Private Class TabPageInfo
Public TabPage As TabPage
Public Visible As Boolean
Public Sub New(ByVal page As TabPage, ByVal v As ...
TabPage = page
Visible = v
End Sub
End Class
Private _tabPageInfos As TabPageInfo() = Nothing
Private _tabControl As TabControl = Nothing
''' <summary>
''' TabPageManagerクラスのインスタンスを作成する
''' </summary>
''' <param name="crl">基になるTabControlオブジェクト<...
Public Sub New(ByVal crl As TabControl)
_tabControl = crl
_tabPageInfos = _
New TabPageInfo(_tabControl.TabPages.Count - ...
Dim i As Integer
For i = 0 To _tabControl.TabPages.Count - 1
_tabPageInfos(i) = _
New TabPageInfo(_tabControl.TabPages(i), ...
Next i
End Sub
''' <summary>
''' TabPageの表示・非表示を変更する
''' </summary>
''' <param name="index">変更するTabPageのIndex番号</p...
''' <param name="v">表示するときはTrue。
''' 非表示にするときはFalse。</param>
Public Sub ChangeTabPageVisible( _
ByVal index As Integer, ByVal v As Boolean)
If _tabPageInfos(index).Visible = v Then
Return
End If
_tabPageInfos(index).Visible = v
_tabControl.SuspendLayout()
_tabControl.TabPages.Clear()
Dim i As Integer
For i = 0 To _tabPageInfos.Length - 1
If _tabPageInfos(i).Visible Then
_tabControl.TabPages.Add(_tabPageInfos(i)...
End If
Next i
_tabControl.ResumeLayout()
End Sub
End Class
}}
#code(csharp){{
public class TabPageManager
{
private class TabPageInfo
{
public TabPage TabPage;
public bool Visible;
public TabPageInfo(TabPage page, bool v)
{
TabPage = page;
Visible = v;
}
}
private TabPageInfo[] _tabPageInfos = null;
private TabControl _tabControl = null;
/// <summary>
/// TabPageManagerクラスのインスタンスを作成する
/// </summary>
/// <param name="crl">基になるTabControlオブジェクト<...
public TabPageManager(TabControl crl)
{
_tabControl = crl;
_tabPageInfos = new TabPageInfo[_tabControl.TabPa...
for(int i = 0; i < _tabControl.TabPages.Count; i++)
_tabPageInfos[i] =
new TabPageInfo(_tabControl.TabPages[i], ...
}
/// <summary>
/// TabPageの表示・非表示を変更する
/// </summary>
/// <param name="index">変更するTabPageのIndex番号</p...
/// <param name="v">表示するときはTrue。
/// 非表示にするときはFalse。</param>
public void ChangeTabPageVisible(int index, bool v)
{
if (_tabPageInfos[index].Visible == v)
return;
_tabPageInfos[index].Visible = v;
_tabControl.SuspendLayout();
_tabControl.TabPages.Clear();
for(int i = 0; i < _tabPageInfos.Length; i++)
{
if (_tabPageInfos[i].Visible)
_tabControl.TabPages.Add(_tabPageInfos[i]...
}
_tabControl.ResumeLayout();
}
}
}}
次に、このTabPageManagerクラスを使ってTabControlのTabPage...
#code(vbnet){{
Private _tabPageManager As TabPageManager
'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
'TabPageManagerオブジェクトの作成
_tabPageManager = New TabPageManager(TabControl1)
End Sub
'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'0番目のTabPageを非表示にする
_tabPageManager.ChangeTabPageVisible(0, False)
End Sub
'Button2のClickイベントハンドラ
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
'0番目のTabPageを表示する
_tabPageManager.ChangeTabPageVisible(0, True)
End Sub
}}
#code(csharp){{
TabPageManager _tabPageManager = null
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
//TabPageManagerオブジェクトの作成
_tabPageManager = new TabPageManager(TabControl1);
}
//Button1のClickイベントハンドラ
private void Button1_Click(object sender, System.EventArg...
{
//0番目のTabPageを非表示にする
_tabPageManager.ChangeTabPageVisible(0, false);
}
//Button2のClickイベントハンドラ
private void button2_Click(object sender, System.EventArg...
{
//0番目のTabPageを表示する
_tabPageManager.ChangeTabPageVisible(0, true);
}
}}
○この記事の基になった掲示板のスレッド
-[[TabControlのタブを非表示にしたい: 投稿者(敬称略) どら...
***DataGridで複数行選択できないようにし、セルがアクティブ...
#column(注意){{
この記事の最新版は「[[DataGridで複数行選択できないように...
}}
''【質問】''
Windowsアプリケーションにおいて、ListViewコントロールのMu...
''【回答】''
まず、DataGridで一つの行だけを選択できるようにする方法を...
-[[Windows Forms FAQ: 5.37 How can I make my DataGrid sup...
-[[TheScarms .NET Code Library: Make the DataGrid support...
これらで紹介されている方法は、DataGridクラスのOnMouseMove...
しかしこのやり方では、キーボードによる複数行の選択を全く...
そこで以下に示すコードでは、OnMouseMoveとOnMouseDownをオ...
#code(vbnet){{
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Namespace Dobon.Samples.Forms
Public Class MyDataGrid
Inherits DataGrid
Private lastRowSelected As Integer = -1
Private rowSelecting As Boolean = False
Protected Overrides Sub OnMouseMove(ByVal e As Mo...
If rowSelecting = False Or _
(e.Button And MouseButtons.Left) <> MouseB...
MyBase.OnMouseMove(e)
End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As Mo...
rowSelecting = False
Dim info As HitTestInfo = Me.HitTest(e.X, e.Y)
If info.Type = HitTestType.Cell Or _
info.Type = HitTestType.RowHeader Then
'選択されている行をリセットする
If lastRowSelected <> -1 Then
Dim cm As CurrencyManager = _
CType(BindingContext(DataSource), _
CurrencyManager)
If lastRowSelected < cm.Count Then
Me.UnSelect(lastRowSelected)
Else
Me.ResetSelection()
End If
End If
If info.Type = HitTestType.Cell Then
'セル上の時
lastRowSelected = -1
MyBase.OnMouseDown(e)
Else If info.Type = HitTestType.RowHeader...
'行ヘッダ上の時
If (Control.ModifierKeys And Keys.Shi...
MyBase.OnMouseDown(e)
Else
CurrentCell = _
New DataGridCell(info.Row, in...
End If
Me.Select(info.Row)
lastRowSelected = info.Row
rowSelecting = True
End If
Else
MyBase.OnMouseDown(e)
End If
End Sub
Protected Overrides Function ProcessCmdKey( _
ByRef msg As Message, ByVal keyData As Keys) ...
Const WM_KEYDOWN As Integer = &H100
Const WM_KEYUP As Integer = &H101
If msg.Msg = WM_KEYDOWN Or msg.Msg = WM_KEYUP...
Dim keyCode As Keys = _
CType(CInt(keyData), Keys) And Keys.K...
'Shift+Up,Downキーでの複数行選択を防止
If (keyData And Keys.Shift) = Keys.Shift ...
(keyCode = Keys.Up Or keyCode = Keys....
Return True
End If 'Shift+Ctrl+Home,Endキーでの複数行...
If (keyData And Keys.Shift) = Keys.Shift ...
(keyData And Keys.Control) = Keys.Con...
(keyCode = Keys.Home Or keyCode = Key...
Return True
End If
'Ctrl+Aキーでの複数行選択を防止
If (keyData And Keys.Control) = Keys.Cont...
keyCode = Keys.A Then
Return True
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class
End Namespace
}}
#code(csharp){{
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Dobon.Samples.Forms
{
public class MyDataGrid : DataGrid
{
private int lastRowSelected = -1;
private bool rowSelecting = false;
protected override void OnMouseMove(MouseEventArg...
{
if (rowSelecting == false || _
(e.Button & MouseButtons.Left) != MouseBu...
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArg...
{
rowSelecting = false;
HitTestInfo info = this.HitTest(e.X, e.Y);
if (info.Type == HitTestType.Cell ||
info.Type == HitTestType.RowHeader)
{
//選択されている行をリセットする
if (lastRowSelected != -1)
{
CurrencyManager cm =
(CurrencyManager) BindingContext[...
if (lastRowSelected < cm.Count)
this.UnSelect(lastRowSelected);
else
this.ResetSelection();
}
if (info.Type == HitTestType.Cell)
{
//セル上の時
lastRowSelected = -1;
base.OnMouseDown(e);
}
else if (info.Type == HitTestType.RowHead...
{
//行ヘッダ上の時
if ((Control.ModifierKeys & Keys.Shif...
base.OnMouseDown(e);
else
CurrentCell =
new DataGridCell(info.Row, in...
this.Select(info.Row);
lastRowSelected = info.Row;
rowSelecting = true;
}
}
else
{
base.OnMouseDown(e);
}
}
protected override bool ProcessCmdKey(
ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_KE...
{
Keys keyCode = (Keys)(int)keyData & Keys....
//Shift+Up,Downキーでの複数行選択を防止
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyCode == Keys.Up || keyCode == Key...
return true;
//Shift+Ctrl+Home,Endキーでの複数行選択を...
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyData & Keys.Control) == Keys.Cont...
(keyCode == Keys.Home || keyCode == K...
return true;
//Ctrl+Aキーでの複数行選択を防止
if ((keyData & Keys.Control) == Keys.Cont...
keyCode == Keys.A)
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
}}
次にセルがアクティブにならないようにする方法を考えます。...
-[[Windows Forms FAQ: 5.41 How can I make my grid never h...
-[[Windows Forms FAQ: 5.83 How can I prevent all the cell...
「5.41」は、GridColumnStyleを使い、GridColumnStyleのEdit...
ここでは、「5.83」の方法を採用し、DataGridのOnControlAdde...
#code(vbnet){{
Protected Overrides Sub OnControlAdded( _
ByVal e As ControlEventArgs)
MyBase.OnControlAdded(e)
If Not TypeOf e.Control Is VScrollBar And _
Not TypeOf e.Control Is HScrollBar Then
Me.Controls.Remove(e.Control)
End If
End Sub
}}
#code(csharp){{
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
if (!(e.Control is VScrollBar) && !(e.Control is HScr...
this.Controls.Remove(e.Control);
}
}}
セルをクリックした時に行全体が選択されるようにするには、...
-[[Windows Forms FAQ: 5.11 How can I select the entire ro...
クリックでも行が選択されるようにするには、CurrentCellChan...
以上の考察により書かれたDataGridクラスの派生クラス(MyData...
#code(vbnet){{
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Namespace Dobon.Samples.Forms
Public Class MyDataGrid
Inherits DataGrid
Private lastRowSelected As Integer = -1
Private rowSelecting As Boolean = False
Protected Overrides Sub OnMouseMove(ByVal e As Mo...
If rowSelecting = False Or _
(e.Button And MouseButtons.Left) <> MouseB...
MyBase.OnMouseMove(e)
End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As Mo...
rowSelecting = False
Dim info As HitTestInfo = Me.HitTest(e.X, e.Y)
If info.Type = HitTestType.Cell Or _
info.Type = HitTestType.RowHeader Then
'選択されている行をリセットする
If lastRowSelected <> -1 Then
Dim cm As CurrencyManager = _
CType(BindingContext(DataSource), _
CurrencyManager)
If lastRowSelected < cm.Count Then
Me.UnSelect(lastRowSelected)
Else
Me.ResetSelection()
End If
End If
If info.Type = HitTestType.Cell Then
'セル上の時
lastRowSelected = -1
MyBase.OnMouseDown(e)
Me.Select(info.Row)
Else If info.Type = HitTestType.RowHeader...
'行ヘッダ上の時
If (Control.ModifierKeys And Keys.Shi...
MyBase.OnMouseDown(e)
Else
CurrentCell = _
New DataGridCell(info.Row, in...
End If
Me.Select(info.Row)
lastRowSelected = info.Row
rowSelecting = True
End If
Else
MyBase.OnMouseDown(e)
End If
End Sub
Protected Overrides Function ProcessCmdKey( _
ByRef msg As Message, ByVal keyData As Keys) ...
Const WM_KEYDOWN As Integer = &H100
Const WM_KEYUP As Integer = &H101
If msg.Msg = WM_KEYDOWN Or msg.Msg = WM_KEYUP...
Dim keyCode As Keys = _
CType(CInt(keyData), Keys) And Keys.K...
'Shift+Up,Downキーでの複数行選択を防止
If (keyData And Keys.Shift) = Keys.Shift ...
(keyCode = Keys.Up Or keyCode = Keys....
Return True
End If
'Shift+Ctrl+Home,Endキーでの複数行選択を...
If (keyData And Keys.Shift) = Keys.Shift ...
(keyData And Keys.Control) = Keys.Con...
(keyCode = Keys.Home Or keyCode = Key...
Return True
End If
'Ctrl+Aキーでの複数行選択を防止
If (keyData And Keys.Control) = Keys.Cont...
keyCode = Keys.A Then
Return True
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
Protected Overrides Sub OnControlAdded( _
ByVal e As ControlEventArgs)
MyBase.OnControlAdded(e)
If Not TypeOf e.Control Is VScrollBar And _
Not TypeOf e.Control Is HScrollBar Then
Me.Controls.Remove(e.Control)
End If
End Sub
End Class
End Namespace
}}
#code(csharp){{
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Dobon.Samples.Forms
{
public class MyDataGrid : DataGrid
{
private int lastRowSelected = -1;
private bool rowSelecting = false;
protected override void OnMouseMove(MouseEventArg...
{
if (rowSelecting == false || _
(e.Button & MouseButtons.Left) != MouseBu...
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArg...
{
rowSelecting = false;
HitTestInfo info = this.HitTest(e.X, e.Y);
if (info.Type == HitTestType.Cell ||
info.Type == HitTestType.RowHeader)
{
//選択されている行をリセットする
if (lastRowSelected != -1)
{
CurrencyManager cm =
(CurrencyManager) BindingContext[...
if (lastRowSelected < cm.Count)
this.UnSelect(lastRowSelected);
else
this.ResetSelection();
}
if (info.Type == HitTestType.Cell)
{
//セル上の時
lastRowSelected = -1;
base.OnMouseDown(e);
this.Select(info.Row);
}
else if (info.Type == HitTestType.RowHead...
{
//行ヘッダ上の時
if ((Control.ModifierKeys & Keys.Shif...
base.OnMouseDown(e);
else
CurrentCell =
new DataGridCell(info.Row, in...
this.Select(info.Row);
lastRowSelected = info.Row;
rowSelecting = true;
}
}
else
{
base.OnMouseDown(e);
}
}
protected override bool ProcessCmdKey(
ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_KE...
{
Keys keyCode = (Keys)(int)keyData & Keys....
//Shift+Up,Downキーでの複数行選択を防止
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyCode == Keys.Up || keyCode == Key...
return true;
//Shift+Ctrl+Home,Endキーでの複数行選択を...
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyData & Keys.Control) == Keys.Cont...
(keyCode == Keys.Home || keyCode == K...
return true;
//Ctrl+Aキーでの複数行選択を防止
if ((keyData & Keys.Control) == Keys.Cont...
keyCode == Keys.A)
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void OnControlAdded(ControlEve...
{
base.OnControlAdded(e);
if (!(e.Control is VScrollBar) &&
!(e.Control is HScrollBar))
this.Controls.Remove(e.Control);
}
}
}
}}
○この記事の基になった掲示板のスレッド
-[[NO TITLE: 投稿者(敬称略) しびっく, ピラルク, 管理人>ht...
**コメント [#xb97c719]
#comment
//これより下は編集しないでください
#pageinfo([[:Category/.NET]],2004-06-01 (火) 06:00:00,DOB...
終了行:
#title(.NETプログラミング研究 第34号)
#navi(.NETプログラミング研究)
#contents
*.NETプログラミング研究 第34号 [#d6888b5d]
**お知らせ [#k62d31be]
過去に発行した「.NETプログラミング研究」のタイトルの一覧...
-[[.NETプログラミング研究 バックナンバー>https://dobon.ne...
バックナンバーのメニュー部分を切り出して列挙して表示して...
**.NET質問箱 [#h26a52f5]
「.NET質問箱」では、「どぼん!のプログラミング掲示板」に...
-[[どぼん!のプログラミング掲示板>https://dobon.net/vb/bb...
***文字列の計算式の計算結果を取得するには? [#d2a14585]
#column(注意){{
この記事の最新版は「[[文字列の計算式の計算結果を取得する>...
}}
''【質問】''
例えば、"(1+6)*5/(7-4)"のような計算式を表す文字列から、そ...
''【回答】''
これには、いろいろな方法が考えられます。
正攻法で行けば、計算式を解析し、計算するコードを自分で書...
-[[A Math Expression Evaluator>http://www.codeproject.com...
さらに、掲示板でArAyさんが紹介されたMSDN Japanの「アルゴ...
-[[アルゴリズム入門:第1章 Visual C# による文字列処理入門>...
このように自分でコードを書く以外の方法も様々あります。
まず、JScript.NETのEvalを使う方法があります。この方法は、...
-[[GotDotNet Message Boards - String to Numeric>http://ww...
この方法によると、まず参照に「Microsoft.Jscript」と「Micr...
#code(vbnet){{
'計算式
Dim exp As String = "(1+6)*5/(7-4)"
Dim ve As Microsoft.JScript.Vsa.VsaEngine = _
Microsoft.JScript.Vsa.VsaEngine.CreateEngine()
Dim result As Double = _
CDbl(Microsoft.JScript.Eval.JScriptEvaluate(exp, ve))
'結果を表示
Console.WriteLine(result)
}}
#code(csharp){{
//計算式
string exp = "(1+6)*5/(7-4)";
Microsoft.JScript.Vsa.VsaEngine ve =
Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
double result =
(double) Microsoft.JScript.Eval.JScriptEvaluate(
exp, ve);
//結果を表示
Console.WriteLine(result);
}}
また、JScriptCodeProviderにより、Evalメソッドを実行する方...
-[[An Eval Function for C# using JScript.NET (JavaScript)...
この方法によると、次のようなコードがかけます。
#code(vbnet){{
'Imports System.Reflection
'Imports System.CodeDom.Compiler
'が宣言されているものとする
'計算式
Dim exp As String = "(1+6)*5/(7-4)"
'計算するためのコード
Dim [source] As String = _
"package Evaluator {" + vbCrLf + _
"class Evaluator {" + vbCrLf + _
"public function Eval(expr : String) : String {" + vb...
"return eval(expr);} } }"
'コンパイルするための準備
Dim cp = New Microsoft.JScript.JScriptCodeProvider
Dim icc As ICodeCompiler = cp.CreateCompiler()
Dim cps As New CompilerParameters
Dim cres As CompilerResults
'メモリ内で出力を生成する
cps.GenerateInMemory = True
'コンパイルする
cres = icc.CompileAssemblyFromSource(cps, [source])
'コンパイルしたアセンブリを取得
Dim asm As [Assembly] = cres.CompiledAssembly
'クラスのTypeを取得
Dim t As Type = asm.GetType("Evaluator.Evaluator")
'インスタンスの作成
Dim eval As Object = Activator.CreateInstance(t)
'Evalメソッドを実行し、結果を取得
Dim result As String = CStr(t.InvokeMember("Eval", _
BindingFlags.InvokeMethod, Nothing, eval, New Object(...
'結果を表示
Console.WriteLine(result)
}}
#code(csharp){{
//using System.Reflection;
//using System.CodeDom.Compiler;
//が宣言されているものとする
//計算式
string exp = "(1+6)*5/(7-4)";
//計算するためのコード
string source =
@"package Evaluator
{
class Evaluator
{
public function Eval(expr : String) : String
{
return eval(expr);
}
}
}";
//コンパイルするための準備
CodeDomProvider cp = new Microsoft.JScript.JScriptCodePro...
ICodeCompiler icc = cp.CreateCompiler();
CompilerParameters cps = new CompilerParameters();
CompilerResults cres;
//メモリ内で出力を生成する
cps.GenerateInMemory = true;
//コンパイルする
cres = icc.CompileAssemblyFromSource(cps, source);
//コンパイルしたアセンブリを取得
Assembly asm = cres.CompiledAssembly;
//クラスのTypeを取得
Type t = asm.GetType("Evaluator.Evaluator");
//インスタンスの作成
object eval = Activator.CreateInstance(t);
//Evalメソッドを実行し、結果を取得
string result = (string) t.InvokeMember("Eval",
BindingFlags.InvokeMethod,
null,
eval,
new object[] {exp});
//結果を表示
Console.WriteLine(result);
}}
さらに、掲示板でピラルクさんが提案されたように、CSharpCod...
-[[Runtime Compilation (A .NET eval statement)>http://www...
-[[Evaluating Mathematical Expressions by Compiling C# Co...
具体的なコードは、例えば、次のようなものです。
#code(vbnet){{
'Imports System.Reflection
'Imports System.CodeDom.Compiler
'が宣言されているものとする
'計算するためのコード
Dim [source] As String = _
"public class MainClass {" + vbCrLf + _
"public static double EVal() {" + vbCrLf + _
"return (1d+6d)*5d/(7d-4d);" + vbCrLf + _
"} }"
'コンパイルするための準備
Dim cp = New Microsoft.CSharp.CSharpCodeProvider
Dim icc As ICodeCompiler = cp.CreateCompiler()
Dim cps As New CompilerParameters
Dim cres As CompilerResults
'メモリ内で出力を生成する
cps.GenerateInMemory = True
'コンパイルする
cres = icc.CompileAssemblyFromSource(cps, [source])
'コンパイルしたアセンブリを取得
Dim asm As [Assembly] = cres.CompiledAssembly
'MainClassクラスのTypeを取得
Dim t As Type = asm.GetType("MainClass")
'EValメソッドを実行し、結果を取得
Dim d As Double = CDbl(t.InvokeMember("EVal", _
BindingFlags.InvokeMethod, Nothing, Nothing, Nothing))
'結果を表示
Console.WriteLine(d)
}}
#code(csharp){{
//using System.CodeDom.Compiler;
//using System.Reflection;
//が宣言されているものとする
//計算するためのコード
string source = @"
public class MainClass
{
public static double EVal()
{
return (1d+6d)*5d/(7d-4d);
}
}";
//コンパイルするための準備
CodeDomProvider cp = new Microsoft.CSharp.CSharpCodeProvi...
ICodeCompiler icc = cp.CreateCompiler();
CompilerParameters cps = new CompilerParameters();
CompilerResults cres;
//メモリ内で出力を生成する
cps.GenerateInMemory = true;
//コンパイルする
cres = icc.CompileAssemblyFromSource(cps, source);
//コンパイルしたアセンブリを取得
Assembly asm = cres.CompiledAssembly;
//MainClassクラスのTypeを取得
Type t = asm.GetType("MainClass");
//EValメソッドを実行し、結果を取得
double d = (double) t.InvokeMember("EVal",
BindingFlags.InvokeMethod,
null,
null,
null);
//結果を表示
Console.WriteLine(d);
}}
前のJScriptCodeProviderを使った方法と比べると、この方法は...
(*1)この問題に関しては、次のページに詳しいです。
-[[Dynamically executing code in .Net>http://www.west-win...
Microsoft Script Controlが使用できるならば、VBScriptやJSC...
#code(vbnet){{
'計算式
Dim exp As String = "(1+6)*5/(7-4)"
Dim t As Type = _
Type.GetTypeFromProgID("MSScriptControl.ScriptControl")
Dim obj As Object = Activator.CreateInstance(t)
t.InvokeMember("Language", _
System.Reflection.BindingFlags.SetProperty, _
Nothing, _
obj, _
New Object() {"vbscript"})
'Eval関数で計算を実行して結果を取得
Dim result As Double = CDbl( _
t.InvokeMember("Eval", _
System.Reflection.BindingFlags.InvokeMethod, _
Nothing, _
obj, _
New Object() {exp}))
'結果を表示
Console.WriteLine(result)
}}
#code(csharp){{
//計算式
string exp = "(1+6)*5/(7-4)";
Type t = Type.GetTypeFromProgID("MSScriptControl.ScriptCo...
object obj = Activator.CreateInstance(t);
t.InvokeMember("Language",
System.Reflection.BindingFlags.SetProperty,
null,
obj,
new object[] {"vbscript"});
//Eval関数で計算を実行して結果を取得
double result = (double) t.InvokeMember("Eval",
System.Reflection.BindingFlags.InvokeMethod,
null,
obj,
new object[] {exp});
//結果を表示
Console.WriteLine(result);
}}
これ以外にも、DataTable.Computeメソッドを使う方法など、ま...
○この記事の基になった掲示板のスレッド
-[[C#で変数の中身を実行する: 投稿者(敬称略) ArAy, ピラル...
-[[文字列で表現した数式を計算: 投稿者(敬称略) nissa.com, ...
***TabControlのTabPageを非表示にするには? [#of915b3e]
#column(注意){{
この記事の最新版は「[[TabControlのTabPageを非表示にする>h...
}}
''【質問】''
TabControlのTabPageにはVisibleプロパティが見つかりません...
''【回答】''
TabPageを非表示にするには、TabControl.TabPagesプロパティ...
TabControlのTabPageを隠し、再び表示させるためのコードを以...
#code(vbnet){{
Public Class TabPageManager
Private Class TabPageInfo
Public TabPage As TabPage
Public Visible As Boolean
Public Sub New(ByVal page As TabPage, ByVal v As ...
TabPage = page
Visible = v
End Sub
End Class
Private _tabPageInfos As TabPageInfo() = Nothing
Private _tabControl As TabControl = Nothing
''' <summary>
''' TabPageManagerクラスのインスタンスを作成する
''' </summary>
''' <param name="crl">基になるTabControlオブジェクト<...
Public Sub New(ByVal crl As TabControl)
_tabControl = crl
_tabPageInfos = _
New TabPageInfo(_tabControl.TabPages.Count - ...
Dim i As Integer
For i = 0 To _tabControl.TabPages.Count - 1
_tabPageInfos(i) = _
New TabPageInfo(_tabControl.TabPages(i), ...
Next i
End Sub
''' <summary>
''' TabPageの表示・非表示を変更する
''' </summary>
''' <param name="index">変更するTabPageのIndex番号</p...
''' <param name="v">表示するときはTrue。
''' 非表示にするときはFalse。</param>
Public Sub ChangeTabPageVisible( _
ByVal index As Integer, ByVal v As Boolean)
If _tabPageInfos(index).Visible = v Then
Return
End If
_tabPageInfos(index).Visible = v
_tabControl.SuspendLayout()
_tabControl.TabPages.Clear()
Dim i As Integer
For i = 0 To _tabPageInfos.Length - 1
If _tabPageInfos(i).Visible Then
_tabControl.TabPages.Add(_tabPageInfos(i)...
End If
Next i
_tabControl.ResumeLayout()
End Sub
End Class
}}
#code(csharp){{
public class TabPageManager
{
private class TabPageInfo
{
public TabPage TabPage;
public bool Visible;
public TabPageInfo(TabPage page, bool v)
{
TabPage = page;
Visible = v;
}
}
private TabPageInfo[] _tabPageInfos = null;
private TabControl _tabControl = null;
/// <summary>
/// TabPageManagerクラスのインスタンスを作成する
/// </summary>
/// <param name="crl">基になるTabControlオブジェクト<...
public TabPageManager(TabControl crl)
{
_tabControl = crl;
_tabPageInfos = new TabPageInfo[_tabControl.TabPa...
for(int i = 0; i < _tabControl.TabPages.Count; i++)
_tabPageInfos[i] =
new TabPageInfo(_tabControl.TabPages[i], ...
}
/// <summary>
/// TabPageの表示・非表示を変更する
/// </summary>
/// <param name="index">変更するTabPageのIndex番号</p...
/// <param name="v">表示するときはTrue。
/// 非表示にするときはFalse。</param>
public void ChangeTabPageVisible(int index, bool v)
{
if (_tabPageInfos[index].Visible == v)
return;
_tabPageInfos[index].Visible = v;
_tabControl.SuspendLayout();
_tabControl.TabPages.Clear();
for(int i = 0; i < _tabPageInfos.Length; i++)
{
if (_tabPageInfos[i].Visible)
_tabControl.TabPages.Add(_tabPageInfos[i]...
}
_tabControl.ResumeLayout();
}
}
}}
次に、このTabPageManagerクラスを使ってTabControlのTabPage...
#code(vbnet){{
Private _tabPageManager As TabPageManager
'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
'TabPageManagerオブジェクトの作成
_tabPageManager = New TabPageManager(TabControl1)
End Sub
'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'0番目のTabPageを非表示にする
_tabPageManager.ChangeTabPageVisible(0, False)
End Sub
'Button2のClickイベントハンドラ
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
'0番目のTabPageを表示する
_tabPageManager.ChangeTabPageVisible(0, True)
End Sub
}}
#code(csharp){{
TabPageManager _tabPageManager = null
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
//TabPageManagerオブジェクトの作成
_tabPageManager = new TabPageManager(TabControl1);
}
//Button1のClickイベントハンドラ
private void Button1_Click(object sender, System.EventArg...
{
//0番目のTabPageを非表示にする
_tabPageManager.ChangeTabPageVisible(0, false);
}
//Button2のClickイベントハンドラ
private void button2_Click(object sender, System.EventArg...
{
//0番目のTabPageを表示する
_tabPageManager.ChangeTabPageVisible(0, true);
}
}}
○この記事の基になった掲示板のスレッド
-[[TabControlのタブを非表示にしたい: 投稿者(敬称略) どら...
***DataGridで複数行選択できないようにし、セルがアクティブ...
#column(注意){{
この記事の最新版は「[[DataGridで複数行選択できないように...
}}
''【質問】''
Windowsアプリケーションにおいて、ListViewコントロールのMu...
''【回答】''
まず、DataGridで一つの行だけを選択できるようにする方法を...
-[[Windows Forms FAQ: 5.37 How can I make my DataGrid sup...
-[[TheScarms .NET Code Library: Make the DataGrid support...
これらで紹介されている方法は、DataGridクラスのOnMouseMove...
しかしこのやり方では、キーボードによる複数行の選択を全く...
そこで以下に示すコードでは、OnMouseMoveとOnMouseDownをオ...
#code(vbnet){{
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Namespace Dobon.Samples.Forms
Public Class MyDataGrid
Inherits DataGrid
Private lastRowSelected As Integer = -1
Private rowSelecting As Boolean = False
Protected Overrides Sub OnMouseMove(ByVal e As Mo...
If rowSelecting = False Or _
(e.Button And MouseButtons.Left) <> MouseB...
MyBase.OnMouseMove(e)
End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As Mo...
rowSelecting = False
Dim info As HitTestInfo = Me.HitTest(e.X, e.Y)
If info.Type = HitTestType.Cell Or _
info.Type = HitTestType.RowHeader Then
'選択されている行をリセットする
If lastRowSelected <> -1 Then
Dim cm As CurrencyManager = _
CType(BindingContext(DataSource), _
CurrencyManager)
If lastRowSelected < cm.Count Then
Me.UnSelect(lastRowSelected)
Else
Me.ResetSelection()
End If
End If
If info.Type = HitTestType.Cell Then
'セル上の時
lastRowSelected = -1
MyBase.OnMouseDown(e)
Else If info.Type = HitTestType.RowHeader...
'行ヘッダ上の時
If (Control.ModifierKeys And Keys.Shi...
MyBase.OnMouseDown(e)
Else
CurrentCell = _
New DataGridCell(info.Row, in...
End If
Me.Select(info.Row)
lastRowSelected = info.Row
rowSelecting = True
End If
Else
MyBase.OnMouseDown(e)
End If
End Sub
Protected Overrides Function ProcessCmdKey( _
ByRef msg As Message, ByVal keyData As Keys) ...
Const WM_KEYDOWN As Integer = &H100
Const WM_KEYUP As Integer = &H101
If msg.Msg = WM_KEYDOWN Or msg.Msg = WM_KEYUP...
Dim keyCode As Keys = _
CType(CInt(keyData), Keys) And Keys.K...
'Shift+Up,Downキーでの複数行選択を防止
If (keyData And Keys.Shift) = Keys.Shift ...
(keyCode = Keys.Up Or keyCode = Keys....
Return True
End If 'Shift+Ctrl+Home,Endキーでの複数行...
If (keyData And Keys.Shift) = Keys.Shift ...
(keyData And Keys.Control) = Keys.Con...
(keyCode = Keys.Home Or keyCode = Key...
Return True
End If
'Ctrl+Aキーでの複数行選択を防止
If (keyData And Keys.Control) = Keys.Cont...
keyCode = Keys.A Then
Return True
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class
End Namespace
}}
#code(csharp){{
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Dobon.Samples.Forms
{
public class MyDataGrid : DataGrid
{
private int lastRowSelected = -1;
private bool rowSelecting = false;
protected override void OnMouseMove(MouseEventArg...
{
if (rowSelecting == false || _
(e.Button & MouseButtons.Left) != MouseBu...
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArg...
{
rowSelecting = false;
HitTestInfo info = this.HitTest(e.X, e.Y);
if (info.Type == HitTestType.Cell ||
info.Type == HitTestType.RowHeader)
{
//選択されている行をリセットする
if (lastRowSelected != -1)
{
CurrencyManager cm =
(CurrencyManager) BindingContext[...
if (lastRowSelected < cm.Count)
this.UnSelect(lastRowSelected);
else
this.ResetSelection();
}
if (info.Type == HitTestType.Cell)
{
//セル上の時
lastRowSelected = -1;
base.OnMouseDown(e);
}
else if (info.Type == HitTestType.RowHead...
{
//行ヘッダ上の時
if ((Control.ModifierKeys & Keys.Shif...
base.OnMouseDown(e);
else
CurrentCell =
new DataGridCell(info.Row, in...
this.Select(info.Row);
lastRowSelected = info.Row;
rowSelecting = true;
}
}
else
{
base.OnMouseDown(e);
}
}
protected override bool ProcessCmdKey(
ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_KE...
{
Keys keyCode = (Keys)(int)keyData & Keys....
//Shift+Up,Downキーでの複数行選択を防止
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyCode == Keys.Up || keyCode == Key...
return true;
//Shift+Ctrl+Home,Endキーでの複数行選択を...
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyData & Keys.Control) == Keys.Cont...
(keyCode == Keys.Home || keyCode == K...
return true;
//Ctrl+Aキーでの複数行選択を防止
if ((keyData & Keys.Control) == Keys.Cont...
keyCode == Keys.A)
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
}}
次にセルがアクティブにならないようにする方法を考えます。...
-[[Windows Forms FAQ: 5.41 How can I make my grid never h...
-[[Windows Forms FAQ: 5.83 How can I prevent all the cell...
「5.41」は、GridColumnStyleを使い、GridColumnStyleのEdit...
ここでは、「5.83」の方法を採用し、DataGridのOnControlAdde...
#code(vbnet){{
Protected Overrides Sub OnControlAdded( _
ByVal e As ControlEventArgs)
MyBase.OnControlAdded(e)
If Not TypeOf e.Control Is VScrollBar And _
Not TypeOf e.Control Is HScrollBar Then
Me.Controls.Remove(e.Control)
End If
End Sub
}}
#code(csharp){{
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
if (!(e.Control is VScrollBar) && !(e.Control is HScr...
this.Controls.Remove(e.Control);
}
}}
セルをクリックした時に行全体が選択されるようにするには、...
-[[Windows Forms FAQ: 5.11 How can I select the entire ro...
クリックでも行が選択されるようにするには、CurrentCellChan...
以上の考察により書かれたDataGridクラスの派生クラス(MyData...
#code(vbnet){{
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Namespace Dobon.Samples.Forms
Public Class MyDataGrid
Inherits DataGrid
Private lastRowSelected As Integer = -1
Private rowSelecting As Boolean = False
Protected Overrides Sub OnMouseMove(ByVal e As Mo...
If rowSelecting = False Or _
(e.Button And MouseButtons.Left) <> MouseB...
MyBase.OnMouseMove(e)
End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As Mo...
rowSelecting = False
Dim info As HitTestInfo = Me.HitTest(e.X, e.Y)
If info.Type = HitTestType.Cell Or _
info.Type = HitTestType.RowHeader Then
'選択されている行をリセットする
If lastRowSelected <> -1 Then
Dim cm As CurrencyManager = _
CType(BindingContext(DataSource), _
CurrencyManager)
If lastRowSelected < cm.Count Then
Me.UnSelect(lastRowSelected)
Else
Me.ResetSelection()
End If
End If
If info.Type = HitTestType.Cell Then
'セル上の時
lastRowSelected = -1
MyBase.OnMouseDown(e)
Me.Select(info.Row)
Else If info.Type = HitTestType.RowHeader...
'行ヘッダ上の時
If (Control.ModifierKeys And Keys.Shi...
MyBase.OnMouseDown(e)
Else
CurrentCell = _
New DataGridCell(info.Row, in...
End If
Me.Select(info.Row)
lastRowSelected = info.Row
rowSelecting = True
End If
Else
MyBase.OnMouseDown(e)
End If
End Sub
Protected Overrides Function ProcessCmdKey( _
ByRef msg As Message, ByVal keyData As Keys) ...
Const WM_KEYDOWN As Integer = &H100
Const WM_KEYUP As Integer = &H101
If msg.Msg = WM_KEYDOWN Or msg.Msg = WM_KEYUP...
Dim keyCode As Keys = _
CType(CInt(keyData), Keys) And Keys.K...
'Shift+Up,Downキーでの複数行選択を防止
If (keyData And Keys.Shift) = Keys.Shift ...
(keyCode = Keys.Up Or keyCode = Keys....
Return True
End If
'Shift+Ctrl+Home,Endキーでの複数行選択を...
If (keyData And Keys.Shift) = Keys.Shift ...
(keyData And Keys.Control) = Keys.Con...
(keyCode = Keys.Home Or keyCode = Key...
Return True
End If
'Ctrl+Aキーでの複数行選択を防止
If (keyData And Keys.Control) = Keys.Cont...
keyCode = Keys.A Then
Return True
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
Protected Overrides Sub OnControlAdded( _
ByVal e As ControlEventArgs)
MyBase.OnControlAdded(e)
If Not TypeOf e.Control Is VScrollBar And _
Not TypeOf e.Control Is HScrollBar Then
Me.Controls.Remove(e.Control)
End If
End Sub
End Class
End Namespace
}}
#code(csharp){{
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Dobon.Samples.Forms
{
public class MyDataGrid : DataGrid
{
private int lastRowSelected = -1;
private bool rowSelecting = false;
protected override void OnMouseMove(MouseEventArg...
{
if (rowSelecting == false || _
(e.Button & MouseButtons.Left) != MouseBu...
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArg...
{
rowSelecting = false;
HitTestInfo info = this.HitTest(e.X, e.Y);
if (info.Type == HitTestType.Cell ||
info.Type == HitTestType.RowHeader)
{
//選択されている行をリセットする
if (lastRowSelected != -1)
{
CurrencyManager cm =
(CurrencyManager) BindingContext[...
if (lastRowSelected < cm.Count)
this.UnSelect(lastRowSelected);
else
this.ResetSelection();
}
if (info.Type == HitTestType.Cell)
{
//セル上の時
lastRowSelected = -1;
base.OnMouseDown(e);
this.Select(info.Row);
}
else if (info.Type == HitTestType.RowHead...
{
//行ヘッダ上の時
if ((Control.ModifierKeys & Keys.Shif...
base.OnMouseDown(e);
else
CurrentCell =
new DataGridCell(info.Row, in...
this.Select(info.Row);
lastRowSelected = info.Row;
rowSelecting = true;
}
}
else
{
base.OnMouseDown(e);
}
}
protected override bool ProcessCmdKey(
ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
if (msg.Msg == WM_KEYDOWN || msg.Msg == WM_KE...
{
Keys keyCode = (Keys)(int)keyData & Keys....
//Shift+Up,Downキーでの複数行選択を防止
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyCode == Keys.Up || keyCode == Key...
return true;
//Shift+Ctrl+Home,Endキーでの複数行選択を...
if ((keyData & Keys.Shift) == Keys.Shift &&
(keyData & Keys.Control) == Keys.Cont...
(keyCode == Keys.Home || keyCode == K...
return true;
//Ctrl+Aキーでの複数行選択を防止
if ((keyData & Keys.Control) == Keys.Cont...
keyCode == Keys.A)
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void OnControlAdded(ControlEve...
{
base.OnControlAdded(e);
if (!(e.Control is VScrollBar) &&
!(e.Control is HScrollBar))
this.Controls.Remove(e.Control);
}
}
}
}}
○この記事の基になった掲示板のスレッド
-[[NO TITLE: 投稿者(敬称略) しびっく, ピラルク, 管理人>ht...
**コメント [#xb97c719]
#comment
//これより下は編集しないでください
#pageinfo([[:Category/.NET]],2004-06-01 (火) 06:00:00,DOB...
ページ名:
▲
▼
[
トップ
] [
新規
|
子ページ作成
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]