- 投稿日:2022-03-22T19:30:10+09:00
cscの作法 その55
概要 cscの作法、調べてみた。 走る人やってみた。 写真 サンプルコード using System; using System.Windows.Forms; using System.Drawing; class form1: Form { PictureBox pb0; Image img; int ind; form1() { Text = "WebBrowser"; ClientSize = new Size(420, 320); pb0 = new PictureBox(); pb0.Width = 85; pb0.Height = 102; img = Image.FromFile("sprite-animation4.png"); pb0.Image = img; ind = 0; Controls.AddRange(new Control[] { pb0 }); Timer timer = new Timer(); timer.Interval = 100; timer.Tick += new EventHandler(timerTick); timer.Start(); } void timerTick(object sender, EventArgs e) { int x; int y; Text = DateTime.Now.ToString("HH:mm:ss"); ind = ind + 1; if (ind > 29) ind = 0; x = (ind % 6) * 85; y = (ind / 6) * 102; Bitmap canvas = new Bitmap(pb0.Width, pb0.Height); Graphics g = Graphics.FromImage(canvas); Rectangle srcRect = new Rectangle(x, y, 85, 102); Rectangle desRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height); g.DrawImage(img, desRect, srcRect, GraphicsUnit.Pixel); g.Dispose(); pb0.Image = canvas; this.Invalidate(); } [STAThread] public static void Main() { Application.Run(new form1()); } } 以上。
- 投稿日:2022-03-22T11:50:29+09:00
Taurus で .NET のテストプロジェクトでロードテストを実施する
はじめに 下記の記事で紹介されていた、Taurus のドキュメントを見ていたら NUnit で作成したテストケースも負荷テストのシナリオに使えそうということで試してみました。 Windows へのインストールなどは下記のドキュメントを参照してください。 テスト対象とテストプロジェクトの準備 テスト対象のプロジェクトと、テストプロジェクトを作成してソリューションに追加します。 テスト対象のプロジェクトは .NET 6.0 でも問題ありませんが、テストプロジェクトは、今のところ .NET Core 3.1 を対象にしないと動かないので注意してください。 mkdir LoadTestSample cd LoadTestSample dotnet new web -o LoadTestSample.WebApp dotnet new nunit -o LoadTestSample.WebApp.Tests -f netcoreapp3.1 dotnet new sln dotnet sln add LoadTestSample.WebApp/LoadTestSample.WebApp.csproj dotnet sln add LoadTestSample.WebApp.Tests/LoadTestSample.WebApp.Tests.csproj 作成された Web アプリを実行します。 > cd LoadTestSample/LoadTestSample.WebApp > dotnet run ビルドしています... info: Microsoft.Hosting.Lifetime[14] Now listening on: https://localhost:7043 info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5049 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: C:\localrepo\LoadTestSample\LoadTestSample.WebApp\ アプリは https://localhost:7043 で実行されているようなので、テストではこのエンドポイントをリクエストして、200 が返ってくるかを確認します。 Test1.cs using NUnit.Framework; using System.Threading.Tasks; using System.Net; using System.Net.Http; namespace LoadTestSample.WebApp.Tests { public class Test1 { private HttpClient _httpClient; [SetUp] public void Setup() { _httpClient = new HttpClient(); } [Test] public async Task Test1() { var response = await _httpClient.GetAsync("https://localhost:7043"); Assert.AreEqual(response.StatusCode, HttpStatusCode.OK); } } } とりあえずテストがうまく動くか実行してみます。 > cd LoadTestSample/LoadTestSample.WebApp > dotnet test Microsoft (R) Test Execution Command Line Tool Version 17.1.0 Copyright (c) Microsoft Corporation. All rights reserved. テスト実行を開始しています。お待ちください... 合計 1 個のテスト ファイルが指定されたパターンと一致しました。 成功! -失敗: 0、合格: 1、スキップ: 0、合計: 1、期間: - LoadTestSample.WebApp.Tests.dll (netcoreapp3.1) 問題なさそうですね。 テスト定義ファイルの追加と実行 公式のサンプルをもとに、テスト定義ファイルを作成します。 とりあえず 50 同時で、シナリオを 100 回実行するようにします。 loadtest.yml execution: - executor: nunit concurrency: 50 iterations: 100 scenario: script: LoadTestSample.WebApp.Tests\bin\Debug\netcoreapp3.1\LoadTestSample.WebApp.Tests.dll 上記の yml を引数に bzt を起動します。 > cd LoadTestSample > bzt .\loadtest.yml 11:28:08 INFO: Taurus CLI Tool v1.16.3 11:28:08 INFO: Starting with configs: ['C:\\Users\\杉山洋一\\.bzt-rc', '.\\loadtest.yml'] 11:28:08 INFO: Configuring... 11:28:08 INFO: Artifacts dir: C:\localrepo\LoadTestSample\2022-03-22_11-28-08.675839 11:28:08 INFO: Preparing... 11:28:08 INFO: Starting... 11:28:08 INFO: Waiting for results... 11:28:09 INFO: Did not mute console logging 11:28:09 INFO: Waiting for finish... 11:29:45 INFO: Changed data analysis delay to 187s 11:30:07 WARNING: Please wait for graceful shutdown... 11:30:07 INFO: Shutting down... 11:30:08 INFO: Post-processing... 11:30:09 INFO: Test duration: 0:02:00 11:30:09 INFO: Samples count: 5000, 0.00% failures 11:30:09 INFO: Average times: total 1.223, latency 0.000, connect 0.000 11:30:09 INFO: Percentiles: +---------------+---------------+ | Percentile, % | Resp. Time, s | +---------------+---------------+ | 0.0 | 0.004 | | 50.0 | 0.196 | | 90.0 | 0.336 | | 95.0 | 0.402 | | 99.0 | 49.248 | | 99.9 | 93.632 | | 100.0 | 93.632 | +---------------+---------------+ 11:30:09 INFO: Request label stats: +-------+--------+---------+--------+-------+ | label | status | succ | avg_rt | error | +-------+--------+---------+--------+-------+ | Test1 | OK | 100.00% | 1.223 | | +-------+--------+---------+--------+-------+ 11:30:09 INFO: Artifacts dir: C:\localrepo\LoadTestSample\2022-03-22_11-28-08.675839 11:30:09 INFO: Done performing with code: 0 一応、無事テストは正常終了したようです。 テスト中はこんな感じのウインドウが表示されました。 Counter の確認 .NET 内部の状況を確認するには、dotnet counters サブコマンドを利用するとわかりやすいです。インストールしていない場合は、次のコマンドラインからインストールできます。 dotnet tool install -g dotnet-counters dotnet counters ps で現在コンピューターで実行されている .NET のプロセスを表示し、dotnet counters collect で収集を開始します。Q をタイプすると収集が完了し、CSV ファイルに結果が出力されます。 > dotnet counters ps 20940 dotnet C:\Program Files\dotnet\dotnet.exe 3828 LoadTestSample.WebApp C:\localrepo\LoadTestSample\LoadTestSample.WebApp\bin\Debug\net6.0\LoadTestSample.WebApp.exe 13740 pwsh C:\Program Files\PowerShell\7\pwsh.exe > dotnet counters collect --process-id 3828 --counters is unspecified. Monitoring System.Runtime counters by default. Starting a counter session. Press Q to quit. File saved to counter.csv Excel のピボットグラフにピボットしてみると、Gen0 のメモリが大量に作成されているのがわかりますね。まぁ、今回のテスト対象は Hello World を表示しているだけなのであんまり面白い結果にはなりませんでしたね。 おわりに 詳しくはまだ触れていないのですが、API の E2E テストを NUnit などで書いている場合は、Taurus を使えばそのまま負荷テストにも転用できそうですね。
- 投稿日:2022-03-22T11:50:29+09:00
Taurus を使って .NET のテストプロジェクトを対象にロードテストを実施する
はじめに 下記の記事で紹介されていた、Taurus のドキュメントを見ていたら NUnit で作成したテストケースも負荷テストのシナリオに使えそうということで試してみました。 Windows へのインストールなどは下記のドキュメントを参照してください。 テスト対象とテストプロジェクトの準備 テスト対象のプロジェクトと、テストプロジェクトを作成してソリューションに追加します。 テスト対象のプロジェクトは .NET 6.0 でも問題ありませんが、テストプロジェクトは、今のところ .NET Core 3.1 を対象にしないと動かないので注意してください。 mkdir LoadTestSample cd LoadTestSample dotnet new web -o LoadTestSample.WebApp dotnet new nunit -o LoadTestSample.WebApp.Tests -f netcoreapp3.1 dotnet new sln dotnet sln add LoadTestSample.WebApp/LoadTestSample.WebApp.csproj dotnet sln add LoadTestSample.WebApp.Tests/LoadTestSample.WebApp.Tests.csproj 作成された Web アプリを実行します。 > cd LoadTestSample/LoadTestSample.WebApp > dotnet run ビルドしています... info: Microsoft.Hosting.Lifetime[14] Now listening on: https://localhost:7043 info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5049 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: C:\localrepo\LoadTestSample\LoadTestSample.WebApp\ アプリは https://localhost:7043 で実行されているようなので、テストではこのエンドポイントをリクエストして、200 が返ってくるかを確認します。 Test1.cs using NUnit.Framework; using System.Threading.Tasks; using System.Net; using System.Net.Http; namespace LoadTestSample.WebApp.Tests { public class Test1 { private HttpClient _httpClient; [SetUp] public void Setup() { _httpClient = new HttpClient(); } [Test] public async Task Test1() { var response = await _httpClient.GetAsync("https://localhost:7043"); Assert.AreEqual(response.StatusCode, HttpStatusCode.OK); } } } とりあえずテストがうまく動くか実行してみます。 > cd LoadTestSample/LoadTestSample.WebApp > dotnet test Microsoft (R) Test Execution Command Line Tool Version 17.1.0 Copyright (c) Microsoft Corporation. All rights reserved. テスト実行を開始しています。お待ちください... 合計 1 個のテスト ファイルが指定されたパターンと一致しました。 成功! -失敗: 0、合格: 1、スキップ: 0、合計: 1、期間: - LoadTestSample.WebApp.Tests.dll (netcoreapp3.1) 問題なさそうですね。 テスト定義ファイルの追加と実行 公式のサンプルをもとに、テスト定義ファイルを作成します。 とりあえず 50 同時で、シナリオを 100 回実行するようにします。 loadtest.yml execution: - executor: nunit concurrency: 50 iterations: 100 scenario: script: LoadTestSample.WebApp.Tests\bin\Debug\netcoreapp3.1\LoadTestSample.WebApp.Tests.dll 上記の yml を引数に bzt を起動します。 > cd LoadTestSample > bzt .\loadtest.yml 11:28:08 INFO: Taurus CLI Tool v1.16.3 11:28:08 INFO: Starting with configs: ['C:\\Users\\杉山洋一\\.bzt-rc', '.\\loadtest.yml'] 11:28:08 INFO: Configuring... 11:28:08 INFO: Artifacts dir: C:\localrepo\LoadTestSample\2022-03-22_11-28-08.675839 11:28:08 INFO: Preparing... 11:28:08 INFO: Starting... 11:28:08 INFO: Waiting for results... 11:28:09 INFO: Did not mute console logging 11:28:09 INFO: Waiting for finish... 11:29:45 INFO: Changed data analysis delay to 187s 11:30:07 WARNING: Please wait for graceful shutdown... 11:30:07 INFO: Shutting down... 11:30:08 INFO: Post-processing... 11:30:09 INFO: Test duration: 0:02:00 11:30:09 INFO: Samples count: 5000, 0.00% failures 11:30:09 INFO: Average times: total 1.223, latency 0.000, connect 0.000 11:30:09 INFO: Percentiles: +---------------+---------------+ | Percentile, % | Resp. Time, s | +---------------+---------------+ | 0.0 | 0.004 | | 50.0 | 0.196 | | 90.0 | 0.336 | | 95.0 | 0.402 | | 99.0 | 49.248 | | 99.9 | 93.632 | | 100.0 | 93.632 | +---------------+---------------+ 11:30:09 INFO: Request label stats: +-------+--------+---------+--------+-------+ | label | status | succ | avg_rt | error | +-------+--------+---------+--------+-------+ | Test1 | OK | 100.00% | 1.223 | | +-------+--------+---------+--------+-------+ 11:30:09 INFO: Artifacts dir: C:\localrepo\LoadTestSample\2022-03-22_11-28-08.675839 11:30:09 INFO: Done performing with code: 0 一応、無事テストは正常終了したようです。 テスト中はこんな感じのウインドウが表示されました。 Counter の確認 .NET 内部の状況を確認するには、dotnet counters サブコマンドを利用するとわかりやすいです。インストールしていない場合は、次のコマンドラインからインストールできます。 dotnet tool install -g dotnet-counters dotnet counters ps で現在コンピューターで実行されている .NET のプロセスを表示し、dotnet counters collect で収集を開始します。Q をタイプすると収集が完了し、CSV ファイルに結果が出力されます。 > dotnet counters ps 20940 dotnet C:\Program Files\dotnet\dotnet.exe 3828 LoadTestSample.WebApp C:\localrepo\LoadTestSample\LoadTestSample.WebApp\bin\Debug\net6.0\LoadTestSample.WebApp.exe 13740 pwsh C:\Program Files\PowerShell\7\pwsh.exe > dotnet counters collect --process-id 3828 --counters is unspecified. Monitoring System.Runtime counters by default. Starting a counter session. Press Q to quit. File saved to counter.csv Excel のピボットグラフにピボットしてみると、Gen0 のメモリが大量に作成されているのがわかりますね。まぁ、今回のテスト対象は Hello World を表示しているだけなのであんまり面白い結果にはなりませんでしたね。 おわりに 詳しくはまだ触れていないのですが、API の E2E テストを NUnit などで書いている場合は、Taurus を使えばそのまま負荷テストにも転用できそうですね。
- 投稿日:2022-03-22T10:55:58+09:00
C#Wordの脚注と相互参照機能を紹介します
脚注は通常、Word文書ページの下部にあり、解釈、説明、または文書内の特定のコンテンツへの関連する参照を提供するために使用されます。同じ脚注がドキュメント内の2つの場所で参照されている場合、脚注は、2番目の引用の代わりに「相互参照」という機能を使用して、前の引用の場所にのみ挿入する必要があります。この記事では、Free Spire.DocコンポーネントとC#を使用して、脚注を挿入し、Wordで相互参照を設定する方法を説明します。 次のコードを使用する前に、Visual StudioでC#アプリケーションを作成し、Spire.Doc.dllをプロジェクトに参照する必要があります。 使用する名前空間: using Spire.Doc; using Spire.Doc.Documents; using Spire.Doc.Fields; 主要なコード //ドキュメントをロードする Document document = new Document(); document.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.docx"); //脚注が必要なテキストと位置している段落を見つける TextSelection ts = document.FindString("楕円の法則", true, true); TextRange textrRange = ts.GetAsOneRange(); Paragraph paragraph = textrRange.OwnerParagraph; //脚注を作成する Footnote footnote = new Footnote(document); footnote.FootnoteType = FootnoteType.Footnote; //脚注のメモテキストを追加し、そのメモ参照マークアップを上付き文字としてフォーマットする Paragraph footPar = footnote.TextBody.AddParagraph(); footPar.AppendText("ドイツの天文学者ケプラーによって提案された惑星運動の3つの法則の1つです。"); footnote.MarkerCharacterFormat.SubSuperScript = SubSuperScript.SuperScript; //テキストの後に脚注を挿入する paragraph.ChildObjects.Insert(paragraph.ChildObjects.IndexOf(textrRange) + 1, footnote); //ステップ2:相互参照フィールドを作成し、脚注にリンクする //脚注のテキストの場所にブックマーク「_FootNote1」を追加する BookmarkStart start = new BookmarkStart(document, "_FootNote1"); BookmarkEnd end = new BookmarkEnd(document, "_FootNote1"); footPar.ChildObjects.Insert(0, start); footPar.ChildObjects.Insert(footPar.ChildObjects.Count - 1, end); //相互参照フィールドを作成し、脚注のメモテキストにブックマークする Field field = new Field(document); field.Type = FieldType.FieldNoteRef; field.Code = @" NOTEREF _FootNote1 \f \h \* MERGEFORMAT "; //同じ脚注とそれが含まれている段落を参照する必要があるテキストを検索する textrRange = document.FindString("軌道法", true, false).GetAsOneRange(); paragraph = textrRange.OwnerParagraph; //テキストの後に相互参照フィールドを挿入する paragraph.ChildObjects.Insert(paragraph.ChildObjects.IndexOf(textrRange) + 1, field); //セパレーターを追加する FieldMark fieldmark = new FieldMark(document, FieldMarkType.FieldSeparator); paragraph.ChildObjects.Insert(paragraph.ChildObjects.IndexOf(textrRange) + 2, fieldmark); //テキストの後に上付き文字を追加する TextRange tr = new TextRange(document); tr.Text = "1"; tr.CharacterFormat.SubSuperScript = SubSuperScript.SuperScript; paragraph.ChildObjects.Insert(paragraph.ChildObjects.IndexOf(textrRange) + 3, tr); //フィールド終了タグを追加する FieldMark fieldEnd = new FieldMark(document, FieldMarkType.FieldEnd); paragraph.ChildObjects.Add(fieldEnd); //ドキュメントを保存する document.SaveToFile("脚注.docx", FileFormat.Docx); 脚注のテキストが本文の内容と一致しないと思う場合は、次のコードを使用してフォントの形式と色を設定できます。 TextRange text = footPar.AppendText("ドイツの天文学者ケプラーによって提案された惑星運動の3つの法則の1つです。"); text.CharacterFormat.FontName = "Arial Black"; text.CharacterFormat.FontSize = 10; text.CharacterFormat.TextColor = Color.DarkGray; 効果は以下のようになります: 今回のWordの脚注と相互参照機能の紹介は以上でした、最後まで読んでいただきありがとうございます。
- 投稿日:2022-03-22T10:55:47+09:00
cscの作法 その54
概要 cscの作法、調べてみた。 アイコン作成ツールやってみた。 参考にしたページ 写真 コンパイル手順 >cd csc >set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH% >csc /unsafe IconMaker.cs IconUtility.cs >IconMaker 以上。
- 投稿日:2022-03-22T10:43:48+09:00
cscの作法 その53
概要 cscの作法、調べてみた。 ネコのイラストやってみた。 参考にしたページ 写真 サンプルコード using System; using System.Windows.Forms; using System.Drawing; class form1: Form { form1() { this.Text = "neko"; ClientSize = new Size(700, 500); } protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; g.DrawEllipse(new Pen(GetFaceBorderColor(), 5), GetFacePosition()); g.DrawPolygon(new Pen(GetFaceBorderColor(), 5), GetLeftEarPosition()); g.DrawPolygon(new Pen(GetFaceBorderColor(), 5), GetRightEarPosition()); g.FillEllipse(new SolidBrush(GetFaceColor()), GetFacePosition()); g.FillPolygon(new SolidBrush(GetFaceColor()), GetLeftEarPosition()); g.FillPolygon(new SolidBrush(GetFaceColor()), GetRightEarPosition()); g.FillEllipse(Brushes.Black, 190, 200, 15, 50); g.FillEllipse(Brushes.Black, 295, 200, 15, 50); g.DrawArc(new Pen(Color.Black, 5), new Rectangle(190, 270, 60, 60), 0, 180); g.DrawArc(new Pen(Color.Black, 5), new Rectangle(250, 270, 60, 60), 0, 180); g.DrawLine(new Pen(Color.Black, 5), new Point(5, 210), new Point(120, 225)); g.DrawLine(new Pen(Color.Black, 5), new Point(0, 250), new Point(120, 250)); g.DrawLine(new Pen(Color.Black, 5), new Point(5, 290), new Point(120, 275)); g.DrawLine(new Pen(Color.Black, 5), new Point(380, 225), new Point(495, 210)); g.DrawLine(new Pen(Color.Black, 5), new Point(380, 250), new Point(500, 250)); g.DrawLine(new Pen(Color.Black, 5), new Point(380, 275), new Point(495, 290)); base.OnPaint(e); } private Color GetFaceColor() { return Color.FromArgb(255, 221, 209, 174); } private Color GetFaceBorderColor() { return Color.FromArgb(255, 182, 156, 78); } private Rectangle GetFacePosition() { return new Rectangle(50, 100, 400, 280); } private Point[] GetLeftEarPosition() { return new Point[] { new Point(430, 30), new Point(430, 210), new Point(300, 110) }; } private Point[] GetRightEarPosition() { return new Point[] { new Point(70, 30), new Point(70, 210), new Point(200, 110) }; } [STAThread] public static void Main() { Application.Run(new form1()); } } 以上。
- 投稿日:2022-03-22T10:35:27+09:00
cscの作法 その52
概要 cscの作法、調べてみた。 シェルピンスキーのギャスケットやってみた。 参考にしたページ 写真 サンプルコード using System; using System.Windows.Forms; using System.Drawing; class form1: Form { private int maxLevel = 6; form1() { BackColor = Color.Black; this.Text = "シェルピンスキーのギャスケット"; ClientSize = new Size(700, 500); } protected override void OnPaint(PaintEventArgs e) { DrawSierpinskiGasket(e.Graphics, 319, 40, 30, 430, 609, 430, 0); base.OnPaint(e); } private void DrawSierpinskiGasket(Graphics g, int x1, int y1, int x2, int y2, int x3, int y3, int level) { if (level == maxLevel) { g.DrawLine(Pens.Lime, x1, y1, x2, y2); g.DrawLine(Pens.Lime, x2, y2, x3, y3); g.DrawLine(Pens.Lime, x3, y3, x1, y1); } else { int xx1 = (int)((x1 + x2) / 2.0); int yy1 = (int)((y1 + y2) / 2.0); int xx2 = (int)((x2 + x3) / 2.0); int yy2 = (int)((y2 + y3) / 2.0); int xx3 = (int)((x3 + x1) / 2.0); int yy3 = (int)((y3 + y1) / 2.0); DrawSierpinskiGasket(g, x1, y1, xx1, yy1, xx3, yy3, level + 1); DrawSierpinskiGasket(g, x2, y2, xx1, yy1, xx2, yy2, level + 1); DrawSierpinskiGasket(g, x3, y3, xx3, yy3, xx2, yy2, level + 1); } } [STAThread] public static void Main() { Application.Run(new form1()); } } 以上。
- 投稿日:2022-03-22T10:25:37+09:00
cscの作法 その51
概要 cscの作法、調べてみた。 コッホ曲線やってみた。 参考にしたページ 写真 サンプルコード using System; using System.Windows.Forms; using System.Drawing; class form1: Form { private const double PAI = 3.141592653589393238462643383279; private const double thetaOf60Degree = 60 * PAI / 180; private int maxLevel = 4; form1() { BackColor = Color.Black; this.Text = "コッホ曲線"; ClientSize = new Size(700, 500); } protected override void OnPaint(PaintEventArgs e) { DrawKochCurve(e.Graphics, 0, 100, 639, 100, 0); base.OnPaint(e); } private void DrawKochCurve(Graphics g, int x1, int y1, int x2, int y2, int level) { if (level == maxLevel) { g.DrawLine(Pens.Yellow, x1, 479 - y1, x2, 479 - y2); } else { int vx = (x2 - x1) / 3; int vy = (y2 - y1) / 3; int xx1 = x1 + vx; int yy1 = y1 + vy; int[] v1 = rotate(thetaOf60Degree, vx, vy); int xx2 = xx1 + v1[0]; int yy2 = yy1 + v1[1]; int[] v2 = rotate(-thetaOf60Degree, vx, vy); int xx3 = xx2 + v2[0]; int yy3 = yy2 + v2[1]; level++; DrawKochCurve(g, x1, y1, xx1, yy1, level); DrawKochCurve(g, xx1, yy1, xx2, yy2, level); DrawKochCurve(g, xx2, yy2, xx3, yy3, level); DrawKochCurve(g, xx3, yy3, x2, y2, level); } } private int[] rotate(double theta, int x, int y) { double sinTheta = Math.Sin(theta); double cosTheta = Math.Cos(theta); int x2 = (int)(cosTheta * x - sinTheta * y); int y2 = (int)(sinTheta * x + cosTheta * y); return new int[] { x2, y2 }; } [STAThread] public static void Main() { Application.Run(new form1()); } } 以上。