┏第18号━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ .NETプログラミング研究 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜メニュー
■.NET Tips
・公開鍵暗号による暗号化
■.NET質問箱
・フォームのイメージを印刷するには?
・GotFocusとLostFocusイベントはどこにいったか?
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜メニュー
───────────────────────────────
■注意事項
───────────────────────────────
一行の文字数に制限があるため、長いURLには途中に改行が入っている
ことがあります。実際には改行は入りませんのでご注意ください。
───────────────────────────────
■.NET質問箱
───────────────────────────────
●公開鍵暗号による暗号化
前回は「秘密鍵暗号方式による暗号化」について説明しましたが、今
回は公開鍵暗号(非対称暗号化方式、公開キー暗号方式)により暗号化、
復号化する方法を紹介します。
公開鍵暗号とは、公開鍵と秘密鍵(個人鍵)の2つの鍵を使って暗号化、
復号化する方法です。公開鍵方式に関して「アスキーデジタル用語辞
典」では次のように説明されています。
「暗号化専用の鍵(公開鍵)と解読専用の鍵(個人鍵)を使って、暗
号化と解読を行なう形式。受信側で事前に公開鍵と個人鍵のペアを用
意し、暗号文の送信側に公開鍵のほうを配布する。送信側は平文を公
開鍵で暗号文に変換できるが、解読はできない。受信側は、個人鍵で
平文に復元可能。公開鍵だけでは解読できないという利点がある。」
・アスキーデジタル用語辞典
http://yougo.ascii24.com/
.NETでは公開キー暗号化アルゴリズムを実装するクラスとして、
DSACryptoServiceProvider(DSA)とRSACryptoServiceProvider(RSA)
の2つが用意されていますが、ここではRSACryptoServiceProviderを使
った例のみを示します。なおDSA、RSAとは何かということ関しては次
のURLが参考になります。
・通信用語の基礎知識 - DSA
http://www.wdic.org/?word=DSA
・通信用語の基礎知識 - RSA
http://www.wdic.org/?word=RSA
次に示すサンプルは、公開鍵暗号により文字列を暗号化、復号化する
ため3つの静的メソッドからなります。まずCreateKeysメソッドで公開
鍵と秘密鍵のペアを作成し、その公開鍵を使ってEncryptメソッドによ
り暗号化します。復号化は秘密鍵を指定してDecryptメソッドにより行
います。
暗号化にはRSACryptoServiceProvider.Encryptメソッドを使用します
が、この時渡す暗号化されるデータにはサイズの制限があります。
OAEPパディング、Direct Encryption、ともにサポートなしのそれぞれ
のケースで暗号化されるデータの最大長の計算法が異なり、このこと
はヘルプ(「RSACryptoServiceProvider.Encrypt メソッド」)で説明
されています。
・RSACryptoServiceProvider.Encrypt メソッド
http://www.microsoft.com/japan/msdn/library/ja/cpref/html
/frlrfsystemsecuritycryptographyrsacryptoserviceproviderclassencrypttopic.
asp
例えばDirect Encryption(高度暗号化パックがインストールされてい
る Microsoft Windows 2000 以降)の場合、
RSACryptoServiceProvider.KeySize プロパティから取得できるキーサ
イズが1024ビットだとすると、暗号化されるデータの最大長は、
1024/8-11=117バイト となります。
下のコードでは暗号化されるデータの最大長のチェックは全く行って
いませんので、ご注意ください。
なお下の例の「RSACryptoServiceProviderオブジェクトの作成」の部
分についてですが、詳しくは「マイクロソフト サポート技術情報
- 322371」をご覧ください。
・マイクロソフト サポート技術情報 - 322371
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q322371
//[C#]・・・・・・・・・・・・・・・・・・・・・・・・・・・・
///
/// 公開鍵と秘密鍵を作成して返す
///
/// 作成された公開鍵(XML形式)
/// 作成された秘密鍵(XML形式)
public static void CreateKeys(out string publicKey, out string privateKey)
{
//RSACryptoServiceProviderオブジェクトの作成
//(Web Service,ASP Page,COM+の時は次のように
//UseMachineKeyStoreを指定する)
System.Security.Cryptography.CspParameters CSPParam =
new System.Security.Cryptography.CspParameters();
CSPParam.Flags =
System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
System.Security.Cryptography.RSACryptoServiceProvider rsa =
new System.Security.Cryptography.RSACryptoServiceProvider(CSPParam);
//公開鍵をXML形式で取得
publicKey = rsa.ToXmlString(false);
//秘密鍵をXML形式で取得
privateKey = rsa.ToXmlString(true);
}
///
/// 公開鍵を使って文字列を暗号化する
///
/// 暗号化する文字列
/// 暗号化に使用する公開鍵(XML形式)
/// 暗号化された文字列
public static string Encrypt(string str, string publicKey)
{
//RSACryptoServiceProviderオブジェクトの作成
System.Security.Cryptography.CspParameters CSPParam =
new System.Security.Cryptography.CspParameters();
CSPParam.Flags =
System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
System.Security.Cryptography.RSACryptoServiceProvider rsa =
new System.Security.Cryptography.RSACryptoServiceProvider(CSPParam);
//公開鍵を指定
rsa.FromXmlString(publicKey);
//暗号化する文字列をバイト配列に
byte[] data = System.Text.Encoding.UTF8.GetBytes(str);
//暗号化する
//(XP以降の場合のみ2項目にTrueを指定し、OAEPパディングを使用できる)
byte[] encryptedData = rsa.Encrypt(data, false);
//Base64で結果を文字列に変換
return System.Convert.ToBase64String(encryptedData);
}
///
/// 秘密鍵を使って文字列を復号化する
///
/// Encryptメソッドにより暗号化された文字列
/// 復号化に必要な秘密鍵(XML形式)
/// 復号化された文字列
public static string Decrypt(string str, string privateKey)
{
//RSACryptoServiceProviderオブジェクトの作成
System.Security.Cryptography.CspParameters CSPParam =
new System.Security.Cryptography.CspParameters();
CSPParam.Flags =
System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
System.Security.Cryptography.RSACryptoServiceProvider rsa =
new System.Security.Cryptography.RSACryptoServiceProvider(CSPParam);
//秘密鍵を指定
rsa.FromXmlString(privateKey);
//復号化する文字列をバイト配列に
byte[] data = System.Convert.FromBase64String(str);
//復号化する
byte[] decryptedData = rsa.Decrypt(data, false);
//結果を文字列に変換
return System.Text.Encoding.UTF8.GetString(decryptedData);
}
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
'[VB.NET]・・・・・・・・・・・・・・・・・・・・・・・・・・
'C#のコードを'C# to VB.NET Translator'で変換し、修正したコードです
'http://www.aspalliance.com/aldotnet/examples/translate.aspx
'
'/
'/ 公開鍵と秘密鍵を作成して返す
'/
'/ 作成された公開鍵(XML形式)
'/ 作成された秘密鍵(XML形式)
Public Shared Sub CreateKeys(ByRef publicKey As String, _
ByRef privateKey As String)
'RSACryptoServiceProviderオブジェクトの作成
'(Web Service,ASP Page,COM+の時は次のように
'UseMachineKeyStoreを指定する)
Dim CSPParam As New System.Security.Cryptography.CspParameters
CSPParam.Flags = _
System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore
Dim rsa As New _
System.Security.Cryptography.RSACryptoServiceProvider(CSPParam)
'公開鍵をXML形式で取得
publicKey = rsa.ToXmlString(False)
'秘密鍵をXML形式で取得
privateKey = rsa.ToXmlString(True)
End Sub
'/
'/ 公開鍵を使って文字列を暗号化する
'/
'/ 暗号化する文字列
'/ 暗号化に使用する公開鍵(XML形式)
'/ 暗号化された文字列
Public Shared Function Encrypt(ByVal str As String, _
ByVal publicKey As String) As String
'RSACryptoServiceProviderオブジェクトの作成
Dim CSPParam As New System.Security.Cryptography.CspParameters
CSPParam.Flags = _
System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore
Dim rsa As New _
System.Security.Cryptography.RSACryptoServiceProvider(CSPParam)
'公開鍵を指定
rsa.FromXmlString(publicKey)
'暗号化する文字列をバイト配列に
Dim data As Byte() = System.Text.Encoding.UTF8.GetBytes(str)
'暗号化する
'(XP以降の場合のみ2項目にTrueを指定し、OAEPパディングを使用できる)
Dim encryptedData As Byte() = rsa.Encrypt(data, False)
'Base64で結果を文字列に変換
Return System.Convert.ToBase64String(encryptedData)
End Function
'/
'/ 秘密鍵を使って文字列を復号化する
'/
'/ Encryptメソッドにより暗号化された文字列
'/ 復号化に必要な秘密鍵(XML形式)
'/ 復号化された文字列
Public Shared Function Decrypt(ByVal str As String, _
ByVal privateKey As String) As String
'RSACryptoServiceProviderオブジェクトの作成
Dim CSPParam As New System.Security.Cryptography.CspParameters
CSPParam.Flags = _
System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore
Dim rsa As New _
System.Security.Cryptography.RSACryptoServiceProvider(CSPParam)
'秘密鍵を指定
rsa.FromXmlString(privateKey)
'復号化する文字列をバイト配列に
Dim data As Byte() = System.Convert.FromBase64String(str)
'復号化する
Dim decryptedData As Byte() = rsa.Decrypt(data, False)
'結果を文字列に変換
Return System.Text.Encoding.UTF8.GetString(decryptedData)
End Function
'・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
・公開鍵暗号による暗号化
http://dobon.net/vb/dotnet/string/rsaencryption.html
───────────────────────────────
■.NET質問箱
───────────────────────────────
●フォームのイメージを印刷するには?
質問:
Visual Basic 6.0ではPrintFormというメソッドがあり、これによりフ
ォームのイメージを印刷することが出来ましたが、同じようなことを.
NETで行うにはどのようにすればよいのでしょうか?
答え:
VB6のPrintFormメソッドに代わるものは.NETにはありません。ヘルプ
によると、
「Visual Basic 6.0 では、フォームのイメージをプリンタに送るとき、
フォームの PrintForm メソッドが使用されていました。PrintForm メ
ソッドは Visual Basic .NET ではサポートされていません。
PrintForm メソッドの結果は、画面の解像度およびプリンタの解像度
に依存するところが大きく、印刷の方法としては推奨されていません
でした。PrintForm メソッドの機能を複製する必要がある場合は、サー
ドパーティ製のグラフィックス ツールに用意されているスクリーン
キャプチャ機能を自動化してフォームのイメージをキャプチャおよび
印刷できます。」
とあります。
・Visual Basic .NET における印刷の変更点
http://www.microsoft.com/japan/msdn/library/ja/Vbcon/html/vbconprintingchangesinvisualbasic70.asp
それではサードパーティ製のスクリーンキャプチャ機能を使うしかな
いかというとそうではなく、Win32 APIでスクリーンキャプチャを行う
方法があり、しかもそれは現在ではヘルプに載っています。
ただし、VB6のPrintFormメソッドがフォームの一部が画面に表示され
ていない場合でもフォーム全体が印刷されるのに対して、この方法で
は表示されていない部分は印刷されません。
・Code: Printing a Windows Form (Visual Basic)
http://msdn.microsoft.com/library/en-us/dv_vbCode/html/vbtskCodeExamplePrintingForm.asp
・Code: Displaying Print Preview for a Windows Form (Visual Basic)
http://msdn.microsoft.com/library/en-us/dv_vbCode/html/vbtskCodeExamplePrintPreviewingForm.asp
・コード : Windows フォームを印刷する (Visual Basic)
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1041/dv_vbcode/html/vbtskcodeexampleprintingform.htm
・コード : Windows フォームの印刷プレビューを表示する (Visual Basic)
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1041/dv_vbcode/html/vbtskcodeexampleprintpreviewingform.htm
以下にこのサンプルコードを書き直した例を示します。使い方として
は、自分自身のフォームを印刷する時、C#では
PrintForm(this);
VB.NETでは
PrintForm(Me)
のようにしてください。
//[C#]・・・・・・・・・・・・・・・・・・・・・・・・・・・・
///
/// フォームのイメージを印刷する
///
/// イメージを印刷するフォーム
public void PrintForm(Form frm)
{
//フォームのイメージを取得する
CaptureScreen(frm);
//フォームのイメージを印刷する
System.Drawing.Printing.PrintDocument PrintDocument1 =
new System.Drawing.Printing.PrintDocument();
PrintDocument1.PrintPage +=
new System.Drawing.Printing.PrintPageEventHandler(
PrintDocument1_PrintPage);
PrintDocument1.Print();
}
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern bool BitBlt(IntPtr hdcDest,
int nXDest, int nYDest, int nWidth, int nHeight,
IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
//フォームのイメージを保存する変数
private Bitmap memoryImage;
//フォームのイメージを取得する
private void CaptureScreen(Form frm)
{
Graphics mygraphics = frm.CreateGraphics();
Size s = frm.Size;
memoryImage = new Bitmap(s.Width, s.Height, mygraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
IntPtr dc1 = mygraphics.GetHdc();
IntPtr dc2 = memoryGraphics.GetHdc();
BitBlt(dc2, 0, 0, frm.ClientRectangle.Width,
frm.ClientRectangle.Height, dc1, 0, 0, 13369376);
mygraphics.ReleaseHdc(dc1);
memoryGraphics.ReleaseHdc(dc2);
}
//PrintDocument1のPrintPageイベントハンドラ
private void PrintDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawImage(memoryImage, 0, 0);
}
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
'[VB.NET]・・・・・・・・・・・・・・・・・・・・・・・・・・
'/
'/ フォームのイメージを印刷する
'/
'/ イメージを印刷するフォーム
Public Sub PrintForm(ByVal frm As Form)
'フォームのイメージを取得する
CaptureScreen(frm)
'フォームのイメージを印刷する
Dim PrintDocument1 As New System.Drawing.Printing.PrintDocument
AddHandler PrintDocument1.PrintPage, _
AddressOf PrintDocument1_PrintPage
PrintDocument1.Print()
End Sub
_
Private Shared Function BitBlt(ByVal hdcDest As IntPtr, _
ByVal nXDest As Integer, ByVal nYDest As Integer, _
ByVal nWidth As Integer, ByVal nHeight As Integer, _
ByVal hdcSrc As IntPtr, _
ByVal nXSrc As Integer, ByVal nYSrc As Integer, _
ByVal dwRop As Integer) As Boolean
End Function
'フォームのイメージを保存する変数
Private memoryImage As Bitmap
'フォームのイメージを取得する
Private Sub CaptureScreen(ByVal frm As Form)
Dim mygraphics As Graphics = frm.CreateGraphics()
Dim s As Size = frm.Size
memoryImage = New Bitmap(s.Width, s.Height, mygraphics)
Dim memoryGraphics As Graphics = Graphics.FromImage(memoryImage)
Dim dc1 As IntPtr = mygraphics.GetHdc()
Dim dc2 As IntPtr = memoryGraphics.GetHdc()
BitBlt(dc2, 0, 0, _
frm.ClientRectangle.Width, frm.ClientRectangle.Height, _
dc1, 0, 0, 13369376)
mygraphics.ReleaseHdc(dc1)
memoryGraphics.ReleaseHdc(dc2)
End Sub
'PrintDocument1のPrintPageイベントハンドラ
Private Sub PrintDocument1_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs)
e.Graphics.DrawImage(memoryImage, 0, 0)
End Sub
'・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
───────────────────────────────
●GotFocusとLostFocusイベントはどこにいったか?
質問:
VB6ではコントロールがフォーカスを受け取った時にGotFocusイベント
が、フォーカスを失った時にLostFocusイベントが発生しましたが、
.NETではこれらのイベントが見つかりません。.NETではどのようにすれ
ばよいのでしょうか?
答え:
.NETでもVB6と同様にGotFocusイベント及びLostFocusイベントは存在
しています。しかしVisual Studio .NETでは、VB.NETの場合はコード
エディタ上の「メソッド名ボックス」に、C#の場合はプロパティウィ
ンドウの「イベント」にGotFocusとLostFocusが表示されません。
GotFocusイベントとLostFocusイベントについて、ヘルプには次のよう
に書いてあります。
「GotFocus イベントおよび LostFocus イベントは、WM_KILLFOCUS
Windows メッセージおよび WM_SETFOCUS Windows メッセージに結び付
けられた、低水準のフォーカス イベントです。一般的に、 GotFocus
イベントおよび LostFocus イベントは、 UICues を更新するときにだ
け使用されます。 Activated イベントおよび Deactivate イベントを
使用する Form クラス以外のすべてのコントロールに対して、 Enter
イベントおよび Leave イベントを使用する必要があります。」
このことから推測すると、GotFocus及びLostFocusイベントの代わりに、
Enter及びLeaveイベントを使うべきという意味でこれらが表示されな
いのかもしれません。
・GotFocus イベント
http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfsystemwindowsformscontrolclassgotfocustopic.asp
・LostFocus イベント
http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfsystemwindowsformscontrolclasslostfocustopic.asp
また、ヘルプの「Visual Basic .NET における TextBox コントロール
の変更点」では、VB6のGotFocus及びLostFocusイベントに代わるもの
は、.NETではEnter及びLeaveイベントとなっています。
・Visual Basic .NET における TextBox コントロールの変更点
http://www.microsoft.com/japan/msdn/library/ja/Vbcon/html/vxconChangesToTextBoxControlInVisualBasicNET.asp
以下にLostFocusイベントを使ったコードを一応書いておきます。
//[C#]・・・・・・・・・・・・・・・・・・・・・・・・・・・・
private void Form1_Load(object sender, System.EventArgs e)
{
//TextBox1のLostFocusイベントハンドラを追加する
TextBox1.LostFocus += new EventHandler(TextBox1_LostFocus);
}
//LostFocusイベントハンドラ
private void TextBox1_LostFocus(object sender, EventArgs e)
{
Console.WriteLine("LostFocusイベントが発生しました。");
}
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
'[VB.NET]・・・・・・・・・・・・・・・・・・・・・・・・・・
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'TextBox1のLostFocusイベントハンドラを追加する
AddHandler TextBox1.LostFocus, AddressOf TextBox1_LostFocus
End Sub
'LostFocusイベントハンドラ
Private Sub TextBox1_LostFocus(ByVal sender As Object, _
ByVal e As EventArgs)
Console.WriteLine("LostFocusイベントが発生しました。")
End Sub
'・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
・どぼん!のVB道掲示板 - focusイベントについて
http://www.sky-j.com/viewlist.php?arg_forum_id=38&arg_thread_id=825&arg_message_id=825
===============================
■このマガジンの購読、購読中止、バックナンバー、説明に関しては
次のページをご覧ください。
http://www.mag2.com/m/0000104516.htm
■発行人・編集人:どぼん!
http://dobon.net
dobon@bigfoot.com
■ご質問等はメールではなく、掲示板へお願いいたします。
http://dobon.net/vb/bbs.html
■上記メールアドレスへのメールは確実に読まれる保障はありません
(スパム、ウィルス対策です)。メールは下記URLのフォームメール
から送信してください。
http://dobon.net/mail.html
Copyright (c) 2003 DOBON! All rights reserved.
===============================