← මුල් පිටුව

WinForms යෙදුමක් සංක්‍රමණය කරන්න

දැනට පවතින Windows Forms විසඳුමක් ස්වයංක්‍රීය නැවත ලිවීමක් මගින් Majorsilence.Forms වෙත ගෙන යන්න — නැතහොත් එය පියවරෙන් පියවර, වරකට එක් පෝරමයක් හෝ එක් පාලකයක් බැගින් කරන්න; ඉතිරි කොටස සැබෑ WinForms හෝ WPF සමඟම build වෙමින් පවතී.

මෙම පිටුව පරිවර්තනයකි. ඉංග්‍රීසි අනුවාදය සමඟ වෙනසක් ඇත්නම්, ඉංග්‍රීසි අනුවාදය නිවැරදි ලෙස සලකන්න. English

WinForms යෙදුමක් XAML framework එකකට සංක්‍රමණය කිරීම යනු සෑම තිරයක්ම නැවත ගොඩනැගීමයි. එය Majorsilence.Forms වෙත සංක්‍රමණය කිරීම බොහෝ දුරට යාන්ත්‍රික නැවත ලිවීමකි — එම පෝරම, එම පාලක, එම සිදුවීම් හසුරුවන (event handlers), වෙනත් namespace එකකට යොමු කර ඇත — සහ ඔබ වෙනුවෙන් එය සිදු කරන CLI මෙවලමක් ඇත.

dotnet tool install -g Majorsilence.Forms.Migrator
majorsilence-migrate MySolution.sln --dry-run --diff

සම්පූර්ණ යොමුව repository එකේ ඇති MIGRATION.md වේ. මෙම පිටුව දළ හැඳින්වීමයි.

මෙවලම ස්ථාපනය කිරීම

migrator මෙවලම nuget.org වෙත .NET tool එකක් ලෙස නිකුත් වන අතර, දැන් එය නිකුත් වන එකම ආකාරය එයයි — කලින් නිකුතු සමඟ එක් එක් වේදිකාව සඳහා self-contained single-file binary එකක්ද අමුණා තිබුණත්, දැන් එසේ නොකෙරේ. එයින් අදහස් වන්නේ යන්ත්‍රයේ .NET runtime එකක් අවශ්‍ය බවයි (පැකේජය RollForward=latestMajor සමඟ net10.0 ඉලක්ක කරයි, එබැවින් නවතම runtime එකක් වුවද ගැටලුවක් නැත).

# ගෝලීය ස්ථාපනය
dotnet tool install -g Majorsilence.Forms.Migrator
majorsilence-migrate --help

# නැතහොත් repo එකකට පමණක්, tool manifest එකක ස්ථිර කර
dotnet new tool-manifest
dotnet tool install Majorsilence.Forms.Migrator
dotnet majorsilence-migrate --help

කිසිවක් ස්ථාපනය නොකිරීමට කැමති නම්, repository එකේ clone එකකින් dotnet run --project tools/Majorsilence.Forms.Migrator -- <input> ලෙස එය ධාවනය කරන්න.

migrator මෙවලම වෙනස් කරන දේ

ඉලක්කය සිදු වන දේ
.csproj / .vbproj UseWindowsForms/UseWPF ඉවත් කරයි, -windows TFM උපසර්ගය ඉවත් කරයි (net8.0-windows → net8.0, net10.0-windows10.0.19041.0 → net10.0) — import කළ .props/.targets තුළද — Windows Desktop framework reference එක ඉවත් කරයි, WinForms-පමණක් පැකේජ (Telerik UI for WinForms, DevExpress, System.Drawing.Common) ඉවත් කරයි, සහ නැවත ලිවීම සැබවින්ම ස්පර්ශ කරන සෑම ව්‍යාපෘතියකටම Majorsilence.Forms සහ backend එකක් එක් කරයි. Central Package Management භාවිත කරන විසඳුම්වලට ගරු කෙරේ: අනුවාදයකින් තොර PackageReference, අනුවාද Directory.Packages.props වෙත එක් කෙරේ
.cs / .vb දිගම-උපසර්ගය-පළමුව (longest-prefix-first) වගුවක් හරහා namespace නැවත ලියයි, එයින් ඇති වන අනුපිටපත් using/Imports පේළි එකතු කරයි, රඳවා ගත් System.Drawing import එකක් නිසා අපැහැදිලි වන නම් කිහිපය සඳහා alias එක් කරයි (SystemColors, ColorTranslator, Telerik හි TabStripItem), සහ ApplicationConfiguration.Initialize() comment out කරයි
Visual Basic විශේෂතා MyType=Empty අදාළ වීම නතර වූ විට නැති වන implicit WinForms constructor එක ඇතුළු කරයි, My.Resources accessor module එකක් ජනනය කරයි, සහ ඉතිරි My.* භාවිතය ගැන අනතුරු ඇඟවීම් දෙයි. My.Application.Info.*, My.Resources.* සහ My.Computer.Name සැබවින්ම ක්‍රියාත්මක කර ඇත; My.Forms, My.Settings, My.User සහ ඉතිරිය තවමත් අනතුරු ඇඟවීම් දෙයි
.resx framework මාරුවෙන් පසුවද පැවතිය යුතු image සහ type references සොයා ගනී
Strongly-typed resource designers ජනනය කළ Resources.Designer.cs-ආකාර ගොනුවල (සහ ඒවායේ පමණක්), System.Resources.ResourceManager යන්න Majorsilence.Forms.ComponentResourceManager බවට පත් වේ, එබැවින් ජනනය කළ (Icon) ResourceManager.GetObject(...) casts පළමු resource කියවීමේදී exception එකක් විසි කරනවා වෙනුවට runtime හිදී සාර්ථක වේ
වාර්තාව එය ස්පර්ශ කළ සියල්ලේ සහ මිනිසෙකු විසින් පරීක්ෂා කළ යුතු යැයි එය සලකන සියල්ලේ Markdown සාරාංශයක් ලියයි

System.Drawing.Common ඉවත් වීම පෙනෙනවාට වඩා වැදගත් ය: එය reference කර තැබුවහොත් System.Drawing.Bitmap/Font/Pen නැවතත් ඒවායේ Majorsilence.Forms.Drawing ආදේශක අසලම scope එකට පැමිණෙන අතර, එවිට සෑම අසුදුසුකම් නොලත් (unqualified) භාවිතයක්ම port එකට resolve වෙනවා වෙනුවට ambiguous reference දෝෂයක් ලෙස අසාර්ථක වේ. තවද “නැවත ලිවීම ස්පර්ශ කරන ව්‍යාපෘති” යනු “WinForms ව්‍යාපෘති” වලට වඩා පුළුල් ය: image helper එකක් ඇති සාමාන්‍ය class library එකක්ද Majorsilence.Forms.Drawing.* වෙත නැවත ලියවෙන අතර එයටද reference එක අවශ්‍ය වේ. System.Drawing තුළ රැඳෙන primitives (Color, Point, Size) පමණක් භාවිත කරන libraries වලට අත නොතැබේ.

ඔබ සැබවින්ම භාවිත කරන විකල්ප

Krypton Toolkit ports සඳහා එක් අමතර පියවරක් ඇත: මෙවලමට type-relationship කරුණු නිවැරදි කළ නොහැක (Majorsilence.Forms Form එකක් Control එකක් නොවේ), එබැවින් repository එක Standard සහ Extended toolkits සඳහා idempotent bridge scripts tools/fixups/ තුළ සපයන අතර, ඉතිරි වැඩ docs/krypton-port-plan.md තුළ ලුහුබඳිනු ලැබේ.

එය git branch එකක එම ස්ථානයේම ධාවනය කරන්න, එවිට සංක්‍රමණය ඔබට කියවිය හැකි, නැවත ධාවනය කළ හැකි සහ ආපසු හැරවිය හැකි diff එකක් වේ:

# කිසිවක් වෙනස් කිරීමට පෙර විෂය පථය බලන්න
majorsilence-migrate MySolution.sln --dry-run --diff

# ඉන්පසු සැබවින්ම කරන්න — git යනු backup එකයි, එබැවින් .bak ගොනු මඟ හරින්න
git checkout -b migrate-to-majorsilence
majorsilence-migrate MySolution.sln --no-backup
git add -A && git commit -m "Migrate to Majorsilence.Forms"

නැවත ලිවීම idempotent වේ, එබැවින් තවත් legacy කේතය merge කළ පසු එය නැවත ධාවනය කිරීම ආරක්ෂිතයි. වාර්තාව කියවන්න: එය සෑම අනතුරු ඇඟවීමක්ම හේතුව අනුව සමූහගත කරයි, සහ වඩාත් සුලභ “skipped project” යනු මෙවලමට parse කිරීමට පෙර SDK style වෙත පරිවර්තනය කළ යුතු පැරණි non-SDK-style .csproj එකකි — එය පූර්ව අවශ්‍යතා පියවරක් මිස සංක්‍රමණයේ හිඩැසක් නොවේ.

Engine දෙකක්

පෙරනිමි engine එක හිතාමතාම පාඨමය නැවත ලියනයකි (textual rewriter) — syntax tree එකක් නැත, symbol resolution නැත. එය කෙටි මඟක් ලෙස ඇසෙන නමුත් එසේ නොවේ: එයින් අදහස් වන්නේ මෙවලම අඩක් සංක්‍රමණය කළ විසඳුමක් මත, කිසිවෙකු තවම port නොකළ type එකක් reference කරන .vb ගොනුවක් මත, දැනට compile නොවන ව්‍යාපෘතියක් මත ක්‍රියා කරන බවයි. Roslyn මත පදනම් වූ මෙවලමක් ව්‍යාපෘතියක් build වන තුරු එයට අත තැබීම ප්‍රතික්ෂේප කරයි, එය legacy කේත පදනමක් මත පළමු අදියරක අරමුණම පරාජය කරයි. එය තත්පර කිහිපයකින් ගොනු දහස් ගණනක් හරහාද ධාවනය වේ.

එය අත්හරින්නේ ව්‍යාපෘති අතර symbol resolution ය: දෙකම හිස් නමින් භාවිත කරන විට ඔබේම Panel class එක System.Windows.Forms.Panel වෙතින් වෙන්කර හඳුනා ගැනීමට එයට නොහැක. එම නිශ්චිත අවස්ථාව සඳහා MSBuildWorkspace සහ සැබෑ symbol resolution භාවිත කරන, තෝරා ගත යුතු (opt-in) --engine roslyn ඇත. එය බොහෝ මන්දගාමී වන අතර load කළ හැකි ව්‍යාපෘතියක් අවශ්‍ය වේ, එබැවින් එය දෙවන අදියරයි — පළමුවැන්න නොවේ. එය එක් එක් ව්‍යාපෘතිය සඳහා ආරක්ෂිතව අසාර්ථක වේ (fails closed): load නොවන එක් ව්‍යාපෘතියක් අනතුරු ඇඟවීමක් සමඟ එම ව්‍යාපෘතියේ ගොනු සඳහා text engine එකට ආපසු වැටේ.

පියවරෙන් පියවර සංක්‍රමණය: සියල්ල එකවර මාරු නොකිරීමට ක්‍රම පහක්

විශාල යෙදුමක් එක් commit එකකින් ගෙන යාමට ඔබට අවශ්‍ය වන්නේ කලාතුරකිනි. දැන් එය පියවර වශයෙන් කිරීමට ක්‍රම කිහිපයක් ඇති අතර, ඒවා එකට භාවිත කළ හැක.

--dual-build: එක් කේත පදනමක්, ඕනෑම stack එකක්

--dual-build මගින් C# ව්‍යාපෘතියක් ඕනෑම stack එකකට එරෙහිව build වන ලෙස තබයි, එය තනි MSBuild property එකකින් මාරු කෙරේ, එබැවින් port කිරීම සිදු වන අතරතුර Windows සංවර්ධකයෙකුට සැබෑ WinForms සමඟ දිගටම compile කළ හැක. UseWindowsForms, -windows TFM සහ WinForms-පමණක් පැකේජ සියල්ල රැඳේ; Majorsilence.Forms ඒවා අසලට එක් කෙරෙන අතර, ගොනුවේ ඉහළ ඇති using System.Windows.Forms; පමණක් #if MAJORSILENCE_FORMS කොන්දේසියක් බවට පත් වේ. එය මාරු කිරීමට Directory.Build.props තුළ <MAJORSILENCE_FORMS>true</MAJORSILENCE_FORMS> සකසන්න. VB සඳහා මෙය ලබා නොදේ — MyType=Empty සම්පූර්ණ My framework එකම අක්‍රිය කරන අතර preprocessor symbol එකකින් එය මාරු කළ නොහැක — එබැවින් --dual-build ලබා දුන් VB ව්‍යාපෘතියක් අනතුරු ඇඟවීමක් සමඟ සාමාන්‍ය ආකාරයට පරිවර්තනය වේ.

WindowsFormsInterop: සම්පූර්ණ පෝරම, දෙපැත්තටම

Windows මත, Majorsilence.Forms.WindowsFormsInterop මගින් Avalonia backend මත ධාවනය වන Majorsilence.Forms යෙදුමක් තුළ සැබෑ System.Windows.Forms පෝරම ධාරණය කරයි (සහ ප්‍රතිලෝමවද), එක් Win32 message pump එකක් බෙදා ගනිමින්, එබැවින් ධාවනය වන යෙදුමක සම්පූර්ණ තිර වරකට එකක් බැගින් ගෙන යා හැක.

WinForms සහ WPF backend: වරකට එක් පාලකයක්

Majorsilence.Forms.WinForms සහ Majorsilence.Forms.Wpf යනු Windows-පමණක් සංක්‍රමණ backend වේ. Avalonia වෙනුවට, Majorsilence.Forms යටින් ඇති ධාරකය (host) සැබෑ System.Windows.Forms කවුළුවකි (නැතහොත් WPF Window එකකි), Skia surface එක GDI bitmap එකක් (නැතහොත් WriteableBitmap එකක්) හරහා ඉදිරිපත් කෙරේ. මෙහි වැදගත්කම කාවැද්දීමේ (embedding) දිශාවයි: port කළ Majorsilence.Forms පාලකයක් සාමාන්‍ය WinForms Control එකක් හෝ WPF FrameworkElement එකක් ලෙස පවතින යෙදුමට නැවත ඇතුළු වේ.

// WinForms ධාරකය
var scene = new Majorsilence.Forms.Panel ();
scene.Controls.Add (new Majorsilence.Forms.Button { Text = "Ported button", Left = 12, Top = 12 });
myWinFormsForm.Controls.Add (scene.ToWinFormsControl ());

// WPF ධාරකය
myWpfGrid.Children.Add (myMfControl.ToWpfElement ());

ToWinFormsForm() / ToWpfWindow() සම්පූර්ණ Form එකක් සඳහාද එයම කරයි, සැබෑ native-modal ShowDialog(owner) ඇතුළුව. පැකේජ දෙකම net8.0-windows සහ net10.0-windows මෙන්ම net48 ද ඉලක්ක කරන අතර, core පැකේජයේ netstandard2.0 build එක සමඟ යුගල වේ, එබැවින් .NET Framework 4.8 යෙදුමකට නවීන .NET වෙත ගෙන යාමට පෙරම Majorsilence.Forms භාවිතය ආරම්භ කළ හැක. WinForms පාලක library එකකට එහි අභ්‍යන්තර කොටස් port කර එහි පාරිභෝගිකයින්ට දිගටම WinForms පාලක සැපයිය හැක.

සියල්ල port කළ පසු, backend පැකේජය Majorsilence.Forms.Avalonia (හෝ Uno, හෝ GTK 4) වෙත මාරු කරන්න, එවිට එම කේතයම බහු-වේදිකා වේ; backend සන්ධියට (seam) ඉහළින් කිසිවක් වෙනස් නොවේ. මෙම backend මත IWebViewFactory නැත, gesture සහාය නැත, සහ Windows නොවන වේදිකාවල ඒවා හිස් placeholder assemblies ලෙස build වේ, එබැවින් බහු-වේදිකා විසඳුමක් තවමත් සෑම තැනකම compile වේ. නිදසුන්: samples/EmbeddingWinForms සහ samples/Gallery.Wpf; පැකේජ READMEs: WinForms, WPF.

WinFormsShims.Compat: namespace නැවත ලිවිය නොහැකි විට

සමහර විට using System.Windows.Forms; නැවත ලිවීම විකල්පයක් නොවේ: තමන්ගේම public API එක System.Windows.Forms/System.Drawing වලට type කර ඇති, සහ පාරිභෝගිකයින්ගෙන් ඔවුන්ගේ කේතය වෙනස් කරන්නැයි ඉල්ලිය නොහැකි, බෙදා හරින ලද පාලක library එකක්. Majorsilence.Forms.WinFormsShims.Compat යනු Majorsilence.Forms මත පදනම් වූ System.Windows.Forms සහ System.Drawing namespace නිකුත් කරන Roslyn source generator එකකි, එබැවින් වෙනස් නොකළ WinForms මූලාශ්‍ර කේතය — Designer.cs ගොනු ඇතුළුව — port එකට එරෙහිව compile වේ. එය සංකල්ප සාධනයක් (proof of concept) ලෙස ප්‍රකාශයට පත් කර ඇත: sealed නොවන සෑම class එකකටම subclasses, sealed drawing leaves (Font, Pen, Bitmap…) සඳහා implicit conversions සහිත wrappers, forwarding static classes (Application, MessageBox, Brushes…), සහ Control හි තමන්ගේම event පවුල. එහි ප්‍රධාන හිඩැස Control හරහාම polymorphic ගබඩා කිරීමයි, එය C# හි single inheritance මගින් වසා දැමිය නොහැක. එය මත රඳා පැවතීමට පෙර README හි scope කොටස කියවන්න; නිදසුන samples/WinFormsCompatDemo වන අතර, එහි සොයාගැනීම් RESULTS.md තුළ ඇත.

Theming.WinForms: කොටස් දෙකටම එක් stylesheet එකක්

මිශ්‍ර යෙදුමකට එක් කවුළුවක් තුළ දෘශ්‍ය පද්ධති දෙකක් ඇත. Majorsilence.Forms.Theming.WinForms මගින් Majorsilence.Forms භාවිත කරන එම CSS තේමාවම සැබෑ System.Windows.Forms පාලකවලට යොදයි — එම tokens, එම selectors, එම diagnostics — පාලක ගසය හරහා ගමන් කරමින් BackColor, ForeColor, Font, FlatAppearance, DataGridView cell styles, tokens වලින් ගොඩනැගූ ToolStripProfessionalRenderer එකක්, සහ DWM හරහා Windows 11 title bar එක සකසමින්. ආරම්භයේදී එක් වරක් WinFormsCssTheme.Apply, එක් එක් පෝරමය සඳහා Track(form), සහ WinForms හට ප්‍රකාශ කළ නොහැකි වූ ඕනෑම දෙයක් සඳහා Diagnostics කියවන්න; කිසිවක් නිහඬව නොසලකා හරිනු නොලැබේ. සහාය න්‍යාසය docs/theming-winforms.md වේ.

එය compile වූ පසු

migrator මෙවලම කේතය build වන තත්ත්වයට ගෙන එයි. එය ඔබට නොකියන දෙය නම් කුමන WinForms හැසිරීම සම්පූර්ණයෙන් ක්‍රියාත්මක කර ඇත්ද, කුමක් ආසන්න කර ඇත්ද, සහ කුමක් හිතාමතාම විෂය පථයෙන් පිටත ඇත්ද යන්නයි — එය ගැළපුම් න්‍යාසය (compatibility matrix) වන අතර, ඊළඟට කියවිය යුතු ලේඛනය එයයි.

පරීක්ෂා කිරීමට පෙර ගැළපුම් ස්තරයේ එක් ගුණාංගයක් හොඳින් තේරුම් ගැනීම වටී: ක්‍රියාත්මක නොකළ සාමාජිකයින් exception විසි කරනවා වෙනුවට no-op (කිසිවක් නොකරයි) හෝ සාධාරණ පෙරනිමි අගයක් ආපසු දෙයි. දෘශ්‍ය විශේෂාංගයක් තවම නොමැති තැන්වලදී පවා සංක්‍රමණය කළ කේතය compile වී ධාවනය වේ, එය නිවැරදි පෙරනිමියයි — නමුත් එයින් අදහස් වන්නේ හිඩැසක් ශබ්ද නඟනවා වෙනුවට නිහඬ විය හැකි බවයි. Image.MakeTransparent එවැන්නකි: වර්ණ-යතුරු කළ sprite sheet එකක් සෑම sprite එකක් පිටුපසම සුදු කොටුවක් සමඟ ඇඳුණු අතර කිසිවක් exception විසි නොකළේය. repository එක දැන් NoOpStubBaselineTests මගින් එයට එරෙහිව ආරක්ෂා වේ, එය හිස් ශරීර සහිත දන්නා public void methods කට්ටලය NoOpStubBaseline.txt තුළ ස්ථිර කරයි (ලියන අවස්ථාවේ 161), එවිට අලුත් stub එකක් පිළිගැනීම සවිඥානික, වාර්තාගත ක්‍රියාවක් වේ. සංක්‍රමණය කළ යෙදුම පරීක්ෂා කරන්න, එය build කිරීම පමණක් නොකරන්න.

ගැළපුමේ කොටස් දෙක සම්බන්ධයෙන් ව්‍යාපෘතිය සිටින තැන:

පරීක්ෂා කිරීමට පෙර MIGRATION.md තුළ හිතාමතා කියවීමට වටින වෙනස්කම් වර්ග දෙකක් ඇත, මන්ද ඒවා කෙසේ වුවද පිරිසිදුව compile වේ:

සංක්‍රමණය කර ඇති සැබෑ යෙදුම්

මෙය න්‍යායික නොවේ. Majorsilence හි තමන්ගේම MPlayercontrol සහ Reporting සංක්‍රමණය වෙමින් පවතින අතර, ගැළපුම් ස්තරය සහ migrator මෙවලම පරීක්ෂා කිරීම සඳහාම විවෘත මූලාශ්‍ර WinForms ව්‍යාපෘති කට්ටලයක් fork කර ඇත — Notepad++ clone එකක්, DarkUI, PKHeX, metroframework, RibbonWinForms, Super Mario Bros remake එකක්, advanceddatagridview සහ තවත් බොහෝ දේ. ඉහත stub baseline වගුවේ හිඩැස් කිහිපයක් මේ ආකාරයෙන් සොයා ගන්නා ලදී. සම්පූර්ණ ලැයිස්තුව repository readme හි Migrated Project Examples කොටසේ ඇත.

යථාර්ථවාදී සැලැස්මක්

  1. branch එකක migrator මෙවලම ධාවනය කරන්න, පළමුව dry-run. වාර්තාව කියවන්න.
  2. එය compile වන තත්ත්වයට ගෙන එන්න. manual-review අනතුරු ඇඟවීම් හරහා වැඩ කරන්න; ඒවා ඉවත් වූ පසු CI වෙත --strict එක් කරන්න.
  3. ඔබේ යෙදුම දැඩි ලෙස රඳා පවතින ඕනෑම දෙයක් සඳහා ගැළපුම් න්‍යාසය පරීක්ෂා කරන්න — DataGridView, අභිරුචි ඇඳීම, තෙවන පාර්ශ්ව පාලක කට්ටල.
  4. ස්වයංක්‍රීයකරණ ගසයට එරෙහිව UI පරීක්ෂණ සකසන්න, එවිට පසුබෑම් (regressions) පෙනේ; එය ඕනෑම OS එකක CI තුළ headless ලෙස ධාවනය වේ.
  5. පළමුව Windows වෙත නිකුත් කරන්න — එම වේදිකාව, අලුත් framework, වරකට එක් විචල්‍යයක්. යෙදුම විශාල නම්, WinForms හෝ WPF backend මත වරකට එක් පාලකයක් බැගින් එය කරන්න. ඉන්පසු backend එක මාරු කර macOS සහ Linux එක් කරන්න.
  6. ඔබේ පැකේජ අනුවාදය ස්ථිර කරන්න. ව්‍යාපෘතිය බීටා අවධියේ ඇති අතර API එක තවමත් ස්ථායී වෙමින් පවතී.

පුහුණු මාර්ගෝපදේශයේ Module 5 මගින් C# සහ VB.NET යන දෙකෙහිම නිදසුන් සමඟ කණ්ඩායමක් මේ හරහා විස්තරාත්මකව රැගෙන යයි.

ඊළඟට