├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE-APACHE ├── LICENSE-GPL ├── Misc ├── Logo.png └── Logo.svg ├── README.md ├── Samples ├── Sample.DirectX │ ├── App.config │ ├── Extensions.cs │ ├── MainWindow.cs │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Sample.DirectX.csproj │ ├── app.manifest │ └── packages.config ├── Sample.Native.Atl │ ├── CAppWindow.cpp │ ├── CAppWindow.h │ ├── Sample.Native.Atl.vcxproj │ ├── Sample.Native.Atl.vcxproj.filters │ ├── main.cpp │ └── pch.h ├── Sample.Native.Win32 │ ├── Sample.Native.Win32.vcxproj │ ├── Sample.Native.Win32.vcxproj.filters │ └── main.cpp ├── Sample.OpenGL │ ├── App.config │ ├── OpenGlWindow.cs │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Sample.OpenGL.csproj │ ├── app.manifest │ └── packages.config ├── Sample.SimpleWindow │ ├── App.config │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Sample.SimpleWindow.csproj │ ├── app.manifest │ └── packages.config ├── Sample.SimulateInput │ ├── App.config │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Sample.SimulateInput.csproj │ ├── app.manifest │ └── packages.config ├── Sample.Skia │ ├── App.config │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Sample.Skia.csproj │ ├── SkiaWindow.cs │ ├── app.manifest │ └── packages.config ├── Sample.Win32 │ ├── App.config │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Sample.Win32.csproj │ ├── app.manifest │ └── packages.config └── WinApi.TestGround │ ├── App.config │ ├── DebugLogger.cs │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── WinApi.TestGround.csproj │ ├── app.manifest │ └── packages.config ├── WinApi.Desktop ├── ApplicationHelpers.cs ├── ConsoleHelpers.cs └── WinApi.Desktop.csproj ├── WinApi.DxUtils ├── Component │ ├── ComposedD3DComponent.cs │ └── Dx11Component.cs ├── Composition │ ├── CompositionHelper.cs │ ├── CompositorCore.cs │ ├── WindowCompositor.cs │ └── WindowSurfaceCompositor.cs ├── Core │ ├── DxgiContainerBase.cs │ └── Interfaces.cs ├── D2D1 │ ├── D2D1Helper.cs │ ├── D2D1MetaFactory.cs │ └── D2D1MetaResource.cs ├── D3D11 │ ├── D3D11Container.cs │ ├── D3D11Dxgi1_2MetaResource.cs │ ├── D3D11DxgiContainer.cs │ ├── D3D11MetaFactory.cs │ └── D3D11MetaResource.cs ├── DxPainter.cs ├── DxVersionInfo.txt ├── DxWindow.cs ├── Helpers.cs └── WinApi.DxUtils.csproj ├── WinApi.Utils ├── DwmWindow.cs ├── DwmWindowHelper.cs ├── NativePixelBuffer.cs ├── Types.cs └── WinApi.Utils.csproj ├── WinApi.Windows.Controls ├── Button.cs ├── EditBox.cs ├── Layouts │ ├── HorizontalStretchLayout.cs │ └── HorizontalStretchLayoutWithInnerMargin.cs ├── StaticBox.cs ├── WinApi.Windows.Controls.csproj └── Window.cs ├── WinApi.sln └── WinApi ├── Core └── Types.cs ├── DwmApi ├── Helpers.cs ├── Methods.cs └── Types.cs ├── Gdi32 ├── CustomTypes.cs ├── Helpers.cs ├── Methods.cs └── Types.cs ├── Kernel32 ├── Constants.cs ├── Helpers.cs ├── Methods.cs └── Types.cs ├── KernelBase └── Methods.cs ├── Properties.cs ├── ShCore ├── Methods.cs └── Types.cs ├── User32 ├── Constants.cs ├── Experimental │ ├── Helpers.cs │ ├── Methods.cs │ └── Types.cs ├── Helpers.cs ├── InputConstants.cs ├── InputTypes.cs ├── Methods.cs └── Types.cs ├── UxTheme ├── Helpers.cs ├── Methods.cs └── Types.cs ├── WinApi.csproj └── Windows ├── ConstructionParams.cs ├── EventLoop.cs ├── EventedWindowCore.cs ├── Helpers ├── MessageBoxHelpers.cs └── MessageHelpers.cs ├── NativeWindow.cs ├── PacketTypes.cs ├── Packetizer.cs ├── WindowCore.cs └── WindowFactory.cs /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | .vs/ 5 | *.VC.db 6 | *.VC.opendb 7 | *project.lock.json 8 | 9 | # User-specific files 10 | *.suo 11 | *.user 12 | *.sln.docstates 13 | Thumbs.db 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | x64/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Roslyn cache directories 26 | *.ide/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | #NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | *_i.c 42 | *_p.c 43 | *_i.h 44 | *.ilk 45 | *.meta 46 | *.obj 47 | *.pch 48 | *.pdb 49 | *.pgc 50 | *.pgd 51 | *.rsp 52 | *.sbr 53 | *.tlb 54 | *.tli 55 | *.tlh 56 | *.tmp 57 | *.tmp_proj 58 | *.log 59 | *.vspscc 60 | *.vssscc 61 | .builds 62 | *.pidb 63 | *.svclog 64 | *.scc 65 | 66 | # Chutzpah Test files 67 | _Chutzpah* 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | *.cachefile 76 | 77 | # Visual Studio profiler 78 | *.psess 79 | *.vsp 80 | *.vspx 81 | 82 | # TFS 2012 Local Workspace 83 | $tf/ 84 | 85 | # Guidance Automation Toolkit 86 | *.gpState 87 | 88 | # ReSharper is a .NET coding add-in 89 | _ReSharper*/ 90 | *.[Rr]e[Ss]harper 91 | *.DotSettings.user 92 | 93 | # JustCode is a .NET coding addin-in 94 | .JustCode 95 | 96 | # TeamCity is a build add-in 97 | _TeamCity* 98 | 99 | # DotCover is a Code Coverage Tool 100 | *.dotCover 101 | 102 | # NCrunch 103 | _NCrunch_* 104 | .*crunch*.local.xml 105 | 106 | # MightyMoose 107 | *.mm.* 108 | AutoTest.Net/ 109 | 110 | # Web workbench (sass) 111 | .sass-cache/ 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.[Pp]ublish.xml 131 | *.azurePubxml 132 | ## TODO: Comment the next line if you want to checkin your 133 | ## web deploy settings but do note that will include unencrypted 134 | ## passwords 135 | #*.pubxml 136 | 137 | # NuGet Packages Directory 138 | packages/* 139 | *.nupkg 140 | ## TODO: If the tool you use requires repositories.config 141 | ## uncomment the next line 142 | #!packages/repositories.config 143 | 144 | # Enable "build/" folder in the NuGet Packages folder since 145 | # NuGet packages use it for MSBuild targets. 146 | # This line needs to be after the ignore of the build folder 147 | # (and the packages folder if the line above has been uncommented) 148 | !packages/build/ 149 | 150 | # Windows Azure Build Output 151 | csx/ 152 | *.build.csdef 153 | 154 | # Windows Store app package directory 155 | AppPackages/ 156 | 157 | # Others 158 | sql/ 159 | *.Cache 160 | ClientBin/ 161 | [Ss]tyle[Cc]op.* 162 | ~$* 163 | *~ 164 | *.dbmdl 165 | *.dbproj.schemaview 166 | *.pfx 167 | *.publishsettings 168 | node_modules/ 169 | 170 | # RIA/Silverlight projects 171 | Generated_Code/ 172 | 173 | # Backup & report files from converting an old project file 174 | # to a newer Visual Studio version. Backup files are not needed, 175 | # because we have git ;-) 176 | _UpgradeReport_Files/ 177 | Backup*/ 178 | UpgradeLog*.XML 179 | UpgradeLog*.htm 180 | 181 | # SQL Server files 182 | *.mdf 183 | *.ldf 184 | 185 | # Business Intelligence projects 186 | *.rdl.data 187 | *.bim.layout 188 | *.bim_*.settings 189 | 190 | # Microsoft Fakes 191 | FakesAssemblies/ 192 | 193 | # LightSwitch generated files 194 | GeneratedArtifacts/ 195 | _Pvt_Extensions/ 196 | ModelManifest.xml -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at pvl@prasannavl.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /Misc/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prasannavl/WinApi/48b583a8e09d39200e71fe5d6a875f862c457744/Misc/Logo.png -------------------------------------------------------------------------------- /Misc/Logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 32 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /Samples/Sample.DirectX/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Samples/Sample.DirectX/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Sample.DirectX 4 | { 5 | public static class RandomExtensions 6 | { 7 | public static float NextFloat(this Random random) 8 | { 9 | return (float) random.NextDouble(); 10 | } 11 | 12 | public static float NextFloat(this Random random, int min, int max) 13 | { 14 | return (float) random.NextDouble()*(max - min) + min; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Samples/Sample.DirectX/MainWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | using SharpDX.Mathematics.Interop; 5 | using WinApi.Core; 6 | using WinApi.DxUtils.Component; 7 | using WinApi.User32; 8 | using WinApi.Utils; 9 | using WinApi.Windows; 10 | 11 | namespace Sample.DirectX 12 | { 13 | public sealed class MainWindow : EventedWindowCore 14 | { 15 | private readonly Dx11Component m_dx = new Dx11Component(); 16 | 17 | protected override void OnCreate(ref CreateWindowPacket packet) 18 | { 19 | this.m_dx.Initialize(this.Handle, this.GetClientSize()); 20 | base.OnCreate(ref packet); 21 | } 22 | 23 | protected override void OnPaint(ref PaintPacket packet) 24 | { 25 | var rand = new Random(); 26 | 27 | var size = this.GetClientSize(); 28 | var w = size.Width; 29 | var h = size.Height; 30 | 31 | this.m_dx.EnsureInitialized(); 32 | try 33 | { 34 | var context = this.m_dx.D2D.Context; 35 | 36 | context.BeginDraw(); 37 | context.Clear(new RawColor4(0, 0, 0, 0f)); 38 | var b = new SolidColorBrush(context, 39 | new RawColor4(rand.NextFloat(), rand.NextFloat(), rand.NextFloat(), 0.4f)); 40 | 41 | context.FillRectangle(new RawRectangleF(200, 200, 500, 700), b); 42 | 43 | for (var i = 0; i < 10; i++) 44 | { 45 | b.Color = new RawColor4(rand.NextFloat(), rand.NextFloat(), rand.NextFloat(), 0.4f); 46 | context.FillEllipse( 47 | new Ellipse(new RawVector2(rand.NextFloat(0, w), rand.NextFloat(0, h)), rand.NextFloat(0, w), 48 | rand.Next(0, h)), b); 49 | context.FillRectangle( 50 | new RawRectangleF(rand.NextFloat(0, w), rand.NextFloat(0, h), rand.NextFloat(0, w), 51 | rand.NextFloat(0, h)), b); 52 | } 53 | b.Dispose(); 54 | 55 | context.EndDraw(); 56 | this.m_dx.D3D.SwapChain.Present(1, 0); 57 | this.Validate(); 58 | } 59 | catch (SharpDXException ex) 60 | { 61 | if (!this.m_dx.PerformResetOnException(ex)) throw; 62 | } 63 | } 64 | 65 | protected override void OnSize(ref SizePacket packet) 66 | { 67 | this.m_dx.Resize(packet.Size); 68 | base.OnSize(ref packet); 69 | } 70 | 71 | protected override void Dispose(bool disposing) 72 | { 73 | this.m_dx.Dispose(); 74 | base.Dispose(disposing); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Samples/Sample.DirectX/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using WinApi.Core; 4 | using WinApi.Kernel32; 5 | using WinApi.User32; 6 | using WinApi.Desktop; 7 | using WinApi.DwmApi; 8 | using WinApi.Gdi32; 9 | using WinApi.UxTheme; 10 | using WinApi.Windows; 11 | using WinApi.Windows.Helpers; 12 | 13 | namespace Sample.DirectX 14 | { 15 | internal class Program 16 | { 17 | static int Main(string[] args) 18 | { 19 | try 20 | { 21 | ApplicationHelpers.SetupDefaultExceptionHandlers(); 22 | var factory = WindowFactory.Create(hBgBrush: IntPtr.Zero); 23 | // Create the window without a dependency on WinApi.Windows.Controls 24 | using ( 25 | var win = factory.CreateWindow(() => new MainWindow(), "Hello", 26 | constructionParams: new FrameWindowConstructionParams(), 27 | exStyles: WindowExStyles.WS_EX_APPWINDOW | WindowExStyles.WS_EX_NOREDIRECTIONBITMAP)) 28 | { 29 | win.CenterToScreen(); 30 | win.Show(); 31 | return new EventLoop().Run(win); 32 | } 33 | } 34 | catch (Exception ex) 35 | { 36 | MessageBoxHelpers.ShowError(ex); 37 | return 1; 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Samples/Sample.DirectX/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Sample.Win32")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Sample.Win32")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("d829fa54-0380-43ef-9e49-73addb653019")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Samples/Sample.DirectX/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | true/pm 56 | 57 | 58 | 59 | 60 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Samples/Sample.DirectX/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Samples/Sample.Native.Atl/CAppWindow.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CAppWindow.h" 3 | 4 | int CAppWindow::Run() 5 | { 6 | auto hwnd = Create(0, 0, L"Hello"); 7 | ShowWindow(SW_SHOWNORMAL); 8 | MSG msg; 9 | BOOL result; 10 | while (result = GetMessage(&msg, 0, 0, 0)) 11 | { 12 | if (result == -1) 13 | return GetLastError(); 14 | TranslateMessage(&msg); 15 | DispatchMessage(&msg); 16 | } 17 | return 0; 18 | } 19 | 20 | LRESULT CAppWindow::OnCreate(LPCREATESTRUCT lpcreatestruct) 21 | { 22 | return 0; 23 | } 24 | 25 | void CAppWindow::OnDestroy() 26 | { 27 | PostQuitMessage(0); 28 | } 29 | 30 | LRESULT CAppWindow::OnEraseBkgnd(HDC hdc) 31 | { 32 | SetMsgHandled(true); 33 | return 1; 34 | } 35 | 36 | void CAppWindow::OnPaint(HDC hdc) 37 | { 38 | PAINTSTRUCT ps; 39 | BeginPaint(&ps); 40 | FillRect(hdc, &ps.rcPaint, (HBRUSH)COLOR_WINDOW); 41 | EndPaint(&ps); 42 | SetMsgHandled(true); 43 | } 44 | -------------------------------------------------------------------------------- /Samples/Sample.Native.Atl/CAppWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pch.h" 4 | 5 | class CAppWindow : public CWindowImpl 6 | { 7 | private: 8 | BEGIN_MSG_MAP(CAppWindow) 9 | MSG_WM_CREATE(OnCreate) 10 | MSG_WM_DESTROY(OnDestroy) 11 | MSG_WM_PAINT(OnPaint) 12 | MSG_WM_ERASEBKGND(OnEraseBkgnd) 13 | END_MSG_MAP() 14 | 15 | public: 16 | DECLARE_WND_CLASS(L"AppWindow") 17 | int Run(); 18 | 19 | protected: 20 | LRESULT OnCreate(LPCREATESTRUCT lpcreatestruct); 21 | void OnDestroy(); 22 | LRESULT OnEraseBkgnd(HDC hdc); 23 | void OnPaint(HDC hdc); 24 | }; 25 | -------------------------------------------------------------------------------- /Samples/Sample.Native.Atl/Sample.Native.Atl.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /Samples/Sample.Native.Atl/main.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CAppWindow.h" 3 | 4 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int) 5 | { 6 | CAppWindow win; 7 | return win.Run(); 8 | } 9 | -------------------------------------------------------------------------------- /Samples/Sample.Native.Atl/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | -------------------------------------------------------------------------------- /Samples/Sample.Native.Win32/Sample.Native.Win32.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Samples/Sample.Native.Win32/main.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | 3 | #include 4 | #include 5 | 6 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 7 | PWSTR pCmdLine, int nCmdShow); 8 | LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, 9 | LPARAM lParam); 10 | 11 | int wmain() 12 | { 13 | wWinMain(nullptr, nullptr, nullptr, 0); 14 | } 15 | 16 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 17 | PWSTR pCmdLine, int nCmdShow) 18 | { 19 | WNDCLASSEX wc = {0}; 20 | wc.hInstance = hInstance; 21 | wc.lpszClassName = L"MainWindow"; 22 | wc.cbSize = sizeof(WNDCLASSEX); 23 | wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION); 24 | wc.hCursor = LoadCursor(nullptr, IDC_ARROW); 25 | wc.style = CS_HREDRAW | CS_VREDRAW; 26 | wc.lpfnWndProc = WindowProc; 27 | auto regRes = RegisterClassEx(&wc); 28 | if (!regRes) 29 | { 30 | std::cerr << "window registration failed" << std::endl; 31 | return regRes; 32 | } 33 | auto hwnd = CreateWindowEx(0, wc.lpszClassName, L"Hello", 34 | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 35 | CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr); 36 | if (hwnd == nullptr) 37 | { 38 | std::cerr << "window couldn't be created" << std::endl; 39 | return -1; 40 | } 41 | 42 | ShowWindow(hwnd, SW_SHOWNORMAL); 43 | 44 | MSG msg = {}; 45 | while (GetMessage(&msg, nullptr, 0, 0)) 46 | { 47 | TranslateMessage(&msg); 48 | DispatchMessage(&msg); 49 | } 50 | return 0; 51 | } 52 | 53 | LRESULT HandleDestroy(HWND hWnd) 54 | { 55 | PostQuitMessage(0); 56 | return 0; 57 | } 58 | 59 | LRESULT HandlePaint(HWND hwnd) 60 | { 61 | PAINTSTRUCT ps; 62 | auto hdc = BeginPaint(hwnd, &ps); 63 | FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW)); 64 | EndPaint(hwnd, &ps); 65 | return 0; 66 | } 67 | 68 | LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 69 | { 70 | switch (uMsg) 71 | { 72 | case WM_ERASEBKGND: 73 | return 1; 74 | case WM_DESTROY: 75 | return HandleDestroy(hwnd); 76 | case WM_PAINT: 77 | return HandlePaint(hwnd); 78 | } 79 | return DefWindowProc(hwnd, uMsg, wParam, lParam); 80 | } 81 | -------------------------------------------------------------------------------- /Samples/Sample.OpenGL/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Samples/Sample.OpenGL/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using OpenGL; 6 | using WinApi.Core; 7 | using WinApi.Desktop; 8 | using WinApi.Gdi32; 9 | using WinApi.User32; 10 | using WinApi.Windows; 11 | using WinApi.Windows.Controls; 12 | using WinApi.Windows.Helpers; 13 | 14 | namespace Sample.OpenGL 15 | { 16 | /// 17 | /// NOTE: This references a modified version of OpenGL.Net, with GitHub PR #13 applied. 18 | /// If it isn't applied, inside the `CreateDeviceContext` method of OpenGlWindowBase 19 | /// the `DeviceContextFactory.Create` should be passed a throw-away `Control` class 20 | /// from Windows.Forms that wraps the Handle IntPtr. Or else, this code will not compile. 21 | /// A patched version of OpenGL.Net with PR #13 applied can be found at 22 | /// https://github.com/prasannavl/OpenGL.Net meanwhile. 23 | /// 24 | class Program 25 | { 26 | static int Main(string[] args) 27 | { 28 | try 29 | { 30 | ApplicationHelpers.SetupDefaultExceptionHandlers(); 31 | Gl.Initialize(); 32 | var factory = WindowFactory.Create(hBgBrush: Gdi32Helpers.GetStockObject(StockObject.BLACK_BRUSH)); 33 | using (var win = Window.Create(factory: factory, text: "Hello")) 34 | { 35 | win.Show(); 36 | return new EventLoop().Run(win); 37 | } 38 | } 39 | catch (Exception ex) 40 | { 41 | MessageBoxHelpers.ShowError(ex); 42 | return 1; 43 | } 44 | } 45 | } 46 | 47 | public sealed class AppWindow : OpenGlWindow 48 | { 49 | protected override void OnGlContextCreated() 50 | { 51 | Gl.MatrixMode(MatrixMode.Projection); 52 | Gl.LoadIdentity(); 53 | Gl.Ortho(0.0, 1.0f, 0.0, 1.0, 0.0, 1.0); 54 | 55 | Gl.MatrixMode(MatrixMode.Modelview); 56 | Gl.LoadIdentity(); 57 | base.OnGlContextCreated(); 58 | } 59 | 60 | protected override void OnGlPaint(ref PaintStruct ps) 61 | { 62 | Gl.Clear(ClearBufferMask.ColorBufferBit); 63 | var size = this.GetClientSize(); 64 | Gl.Viewport(0, 0, size.Width, size.Height); 65 | Gl.Begin(PrimitiveType.Triangles); 66 | Gl.Color3(1.0f, 0.0f, 0.0f); 67 | Gl.Vertex2(0.0f, 0.0f); 68 | Gl.Color3(0.0f, 1.0f, 0.0f); 69 | Gl.Vertex2(0.5f, 1.0f); 70 | Gl.Color3(0.0f, 0.0f, 1.0f); 71 | Gl.Vertex2(1.0f, 0.0f); 72 | Gl.End(); 73 | this.DeviceContext.SwapBuffers(); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Samples/Sample.OpenGL/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Sample.OpenGL")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Sample.OpenGL")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("d58d8e28-296c-405a-b295-ad13c577d5ae")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Samples/Sample.OpenGL/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | true/pm 56 | 57 | 58 | 59 | 60 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Samples/Sample.OpenGL/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Samples/Sample.SimpleWindow/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Samples/Sample.SimpleWindow/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using WinApi.Gdi32; 7 | using WinApi.User32; 8 | using WinApi.Windows; 9 | using WinApi.Windows.Controls; 10 | 11 | namespace Sample.SimpleWindow 12 | { 13 | internal class Program 14 | { 15 | static int Main(string[] args) 16 | { 17 | using (var win = Window.Create("Hello")) 18 | { 19 | win.Show(); 20 | return new EventLoop().Run(win); 21 | } 22 | } 23 | } 24 | 25 | public class AppWindow : Window 26 | { 27 | protected override void OnPaint(ref PaintPacket packet) 28 | { 29 | PaintStruct ps; 30 | var hdc = this.BeginPaint(out ps); 31 | User32Methods.FillRect(hdc, ref ps.PaintRect, 32 | Gdi32Helpers.GetStockObject(StockObject.WHITE_BRUSH)); 33 | this.EndPaint(ref ps); 34 | base.OnPaint(ref packet); 35 | } 36 | 37 | protected override void OnMessage(ref WindowMessage msg) 38 | { 39 | switch (msg.Id) 40 | { 41 | // Note: OnEraseBkgnd method is already available in 42 | // EventedWindowCore, but directly intercepted here 43 | // just for the sake of overriding the 44 | // message loop. 45 | // Also, note that the message loop is 46 | // short-cicuited here. 47 | 48 | case WM.ERASEBKGND: 49 | { 50 | // I can even build the loop only on pay-per-use 51 | // basis, when I need it since all the Packets decoding, 52 | // and encoding are cleanly abstracted away into the Packet 53 | // structs itself. 54 | // 55 | // fixed (var msgPtr = &msg) 56 | // { 57 | // var packet = new EraseBkgndPacket(msg); 58 | // // Do anything you want with the packet. 59 | // } 60 | // return; 61 | 62 | msg.Result = new IntPtr(1); 63 | return; 64 | } 65 | } 66 | base.OnMessage(ref msg); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Samples/Sample.SimpleWindow/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Sample.SimpleWindow")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Sample.SimpleWindow")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("3f1b11ae-9a3d-4523-91fc-7457cad687ab")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Samples/Sample.SimpleWindow/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | true/pm 56 | 57 | 58 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Samples/Sample.SimpleWindow/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Samples/Sample.SimulateInput/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Samples/Sample.SimulateInput/Program.cs: -------------------------------------------------------------------------------- 1 | using NetCoreEx.Geometry; 2 | using System; 3 | using System.Runtime.ExceptionServices; 4 | using WinApi.Core; 5 | using WinApi.Desktop; 6 | using WinApi.User32; 7 | using WinApi.Windows; 8 | using WinApi.Windows.Controls; 9 | using WinApi.Windows.Controls.Layouts; 10 | 11 | namespace Sample.SimulateInput 12 | { 13 | class Program 14 | { 15 | [HandleProcessCorruptedStateExceptions] 16 | static int Main(string[] args) 17 | { 18 | ApplicationHelpers.SetupDefaultExceptionHandlers(); 19 | 20 | try 21 | { 22 | var factory = WindowFactory.Create(); 23 | using (var win = Window.Create(factory: factory, text: "Hello")) 24 | { 25 | win.Show(); 26 | return new EventLoop().Run(win); 27 | } 28 | } 29 | catch (Exception ex) { 30 | ApplicationHelpers.ShowCriticalError(ex); 31 | } 32 | return 0; 33 | } 34 | 35 | public sealed class SampleWindow : Window 36 | { 37 | private readonly Input[] m_inputs = new Input[11]; 38 | private readonly HorizontalStretchLayout m_layout = new HorizontalStretchLayout(); 39 | private EditBox m_editBox; 40 | private StaticBox m_textBox; 41 | private IntPtr m_timerId; 42 | private TimerProc m_timerProc; 43 | private int m_timesExecuted; 44 | 45 | protected override void OnCreate(ref CreateWindowPacket packet) 46 | { 47 | this.m_textBox = StaticBox.Create( 48 | "Ahoy!", 49 | hParent: this.Handle); 50 | 51 | this.m_editBox = EditBox.Create( 52 | "Nothing here yet.", 53 | hParent: this.Handle, 54 | controlStyles: 55 | EditBox.EditStyles.ES_MULTILINE | EditBox.EditStyles.ES_WANTRETURN | 56 | (EditBox.EditStyles) WindowStyles.WS_VSCROLL); 57 | 58 | this.m_layout.ClientArea = this.GetClientRect(); 59 | this.m_layout.Margin = new Rectangle(10, 10, 10, 10); 60 | this.m_layout.Children.Add(this.m_textBox); 61 | this.m_layout.Children.Add(this.m_editBox); 62 | this.m_layout.PerformLayout(); 63 | this.m_timerProc = (wnd, uMsg, eventId, millis) => 64 | { 65 | try 66 | { 67 | this.m_timesExecuted++; 68 | Input.InitKeyboardInput(out this.m_inputs[0], VirtualKey.H, false); 69 | Input.InitKeyboardInput(out this.m_inputs[1], VirtualKey.H, true); 70 | Input.InitKeyboardInput(out this.m_inputs[3], VirtualKey.E, false); 71 | Input.InitKeyboardInput(out this.m_inputs[4], VirtualKey.E, true); 72 | Input.InitKeyboardInput(out this.m_inputs[5], VirtualKey.L, false); 73 | Input.InitKeyboardInput(out this.m_inputs[6], VirtualKey.L, true); 74 | Input.InitKeyboardInput(out this.m_inputs[7], VirtualKey.L, false); 75 | Input.InitKeyboardInput(out this.m_inputs[8], VirtualKey.L, true); 76 | Input.InitKeyboardInput(out this.m_inputs[9], VirtualKey.O, false); 77 | Input.InitKeyboardInput(out this.m_inputs[10], VirtualKey.O, true); 78 | var x = User32Helpers.SendInput(this.m_inputs); 79 | } 80 | catch (Exception ex) { 81 | this.m_editBox.SetText($"ERROR: {ex.Message}\r\n{ex.StackTrace}"); 82 | } 83 | }; 84 | 85 | this.m_timerId = User32Methods.SetTimer(this.Handle, IntPtr.Zero, 20, this.m_timerProc); 86 | base.OnCreate(ref packet); 87 | } 88 | 89 | protected override void OnKey(ref KeyPacket packet) 90 | { 91 | var key = packet.Key; 92 | var inputState = packet.InputState; 93 | var str = $"\r\n{DateTime.Now} :" + 94 | $" {key} => {inputState.IsKeyUpTransition}; " + 95 | $"{inputState.RepeatCount}; " + 96 | $"{inputState.ScanCode}; " + 97 | $"{inputState.IsContextual}; " + 98 | $"{inputState.IsExtendedKey}" + "\r\n" + 99 | $"No. of text display changes: {this.m_timesExecuted}" + "\0"; 100 | this.m_textBox.SetText(str); 101 | base.OnKey(ref packet); 102 | } 103 | 104 | protected override void OnMouseButton(ref MouseButtonPacket packet) 105 | { 106 | var button = packet.Button; 107 | var isButtonDown = packet.IsButtonDown; 108 | if ((button == MouseButton.Left) && isButtonDown) this.SetFocus(); 109 | base.OnMouseButton(ref packet); 110 | } 111 | 112 | protected override void OnSize(ref SizePacket packet) 113 | { 114 | var size = packet.Size; 115 | this.m_layout.SetSize(ref size); 116 | base.OnSize(ref packet); 117 | } 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /Samples/Sample.SimulateInput/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Sample.SimulateInput")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Sample.SimulateInput")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("62b305ba-bd58-48d0-ad77-ef64f987ca5a")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Samples/Sample.SimulateInput/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Samples/Sample.SimulateInput/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Samples/Sample.Skia/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Samples/Sample.Skia/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | using SkiaSharp; 6 | using WinApi.DwmApi; 7 | using WinApi.User32; 8 | using WinApi.UxTheme; 9 | using System.Linq; 10 | using WinApi.Desktop; 11 | using WinApi.Gdi32; 12 | using WinApi.User32.Experimental; 13 | using WinApi.Windows; 14 | using WinApi.Windows.Helpers; 15 | using NetCoreEx.Geometry; 16 | 17 | namespace Sample.Skia 18 | { 19 | class Program 20 | { 21 | static int Main(string[] args) 22 | { 23 | try 24 | { 25 | ApplicationHelpers.SetupDefaultExceptionHandlers(); 26 | // Using it without a dependency on WinApi.Windows.Controls 27 | var factory = WindowFactory.Create(hBgBrush: IntPtr.Zero); 28 | using (var win = factory.CreateWindow(() => new SkiaWindow(), "Hello", 29 | constructionParams: new FrameWindowConstructionParams())) 30 | { 31 | win.Show(); 32 | return new EventLoop().Run(win); 33 | } 34 | } 35 | catch (Exception ex) 36 | { 37 | MessageBoxHelpers.ShowError(ex); 38 | return 1; 39 | } 40 | } 41 | } 42 | 43 | public sealed class SkiaWindow : SkiaWindowBase 44 | { 45 | protected override void OnSkiaPaint(SKSurface surface) 46 | { 47 | var windowRect = this.GetWindowRect(); 48 | var clientRect = new Rectangle(windowRect.Width, windowRect.Height); 49 | var canvas = surface.Canvas; 50 | canvas.Clear(new SKColor(120, 50, 70, 200)); 51 | var textPainter = new SKPaint {TextSize = 35, IsAntialias = true}; 52 | var str = "Hello there!"; 53 | var textBounds = new SKRect(); 54 | var m = textPainter.MeasureText(str, ref textBounds); 55 | canvas.DrawText(str, (clientRect.Width - textBounds.Width)/2, (clientRect.Height - textBounds.Height)/2, 56 | textPainter); 57 | 58 | base.OnSkiaPaint(surface); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Samples/Sample.Skia/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Sample.Skia")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Sample.Skia")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("5ff4bac3-d221-4023-9ee9-51c1f5c85d50")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Samples/Sample.Skia/SkiaWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SkiaSharp; 3 | using WinApi.Core; 4 | using WinApi.Desktop; 5 | using WinApi.DwmApi; 6 | using WinApi.Gdi32; 7 | using WinApi.User32; 8 | using WinApi.User32.Experimental; 9 | using WinApi.Utils; 10 | using WinApi.UxTheme; 11 | using WinApi.Windows; 12 | using NetCoreEx.Geometry; 13 | 14 | namespace Sample.Skia 15 | { 16 | public class SkiaPainter 17 | { 18 | public static void ProcessPaint(ref PaintPacket packet, NativePixelBuffer pixelBuffer, 19 | Action handler) 20 | { 21 | var hwnd = packet.Hwnd; 22 | Rectangle clientRect; 23 | User32Methods.GetClientRect(hwnd, out clientRect); 24 | var size = clientRect.Size; 25 | pixelBuffer.EnsureSize(size.Width, size.Height); 26 | PaintStruct ps; 27 | var hdc = User32Methods.BeginPaint(hwnd, out ps); 28 | var skPainted = false; 29 | try 30 | { 31 | using (var surface = SKSurface.Create( 32 | size.Width, 33 | size.Height, 34 | SKColorType.Bgra8888, 35 | SKAlphaType.Premul, 36 | pixelBuffer.Handle, 37 | pixelBuffer.Stride)) 38 | { 39 | if (surface != null) 40 | { 41 | handler(surface); 42 | skPainted = true; 43 | } 44 | } 45 | } 46 | finally 47 | { 48 | if (skPainted) Gdi32Helpers.SetRgbBitsToDevice(hdc, size.Width, size.Height, pixelBuffer.Handle); 49 | User32Methods.EndPaint(hwnd, ref ps); 50 | } 51 | } 52 | } 53 | 54 | public class SkiaWindowBase : EventedWindowCore 55 | { 56 | private readonly NativePixelBuffer m_pixelBuffer = new NativePixelBuffer(); 57 | 58 | protected virtual void OnSkiaPaint(SKSurface surface) {} 59 | 60 | protected override void OnPaint(ref PaintPacket packet) 61 | { 62 | SkiaPainter.ProcessPaint(ref packet, this.m_pixelBuffer, this.OnSkiaPaint); 63 | } 64 | 65 | protected override void Dispose(bool disposing) 66 | { 67 | this.m_pixelBuffer.Dispose(); 68 | base.Dispose(disposing); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Samples/Sample.Skia/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Samples/Sample.Skia/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Samples/Sample.Win32/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Samples/Sample.Win32/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using WinApi.Gdi32; 8 | using WinApi.Kernel32; 9 | using WinApi.User32; 10 | 11 | namespace Sample.Win32 12 | { 13 | internal class Program 14 | { 15 | static int Main(string[] args) 16 | { 17 | var instanceHandle = Kernel32Methods.GetModuleHandle(IntPtr.Zero); 18 | 19 | var wc = new WindowClassEx 20 | { 21 | Size = (uint) Marshal.SizeOf(), 22 | ClassName = "MainWindow", 23 | CursorHandle = User32Helpers.LoadCursor(IntPtr.Zero, SystemCursor.IDC_ARROW), 24 | IconHandle = User32Helpers.LoadIcon(IntPtr.Zero, SystemIcon.IDI_APPLICATION), 25 | Styles = WindowClassStyles.CS_HREDRAW | WindowClassStyles.CS_VREDRAW, 26 | BackgroundBrushHandle = new IntPtr((int) StockObject.WHITE_BRUSH), 27 | WindowProc = WindowProc, 28 | InstanceHandle = instanceHandle 29 | }; 30 | 31 | var resReg = User32Methods.RegisterClassEx(ref wc); 32 | if (resReg == 0) 33 | { 34 | Console.Error.WriteLine("registration failed"); 35 | return -1; 36 | } 37 | 38 | var hwnd = User32Methods.CreateWindowEx(WindowExStyles.WS_EX_APPWINDOW, 39 | wc.ClassName, "Hello", WindowStyles.WS_OVERLAPPEDWINDOW, 40 | (int) CreateWindowFlags.CW_USEDEFAULT, (int) CreateWindowFlags.CW_USEDEFAULT, 41 | (int) CreateWindowFlags.CW_USEDEFAULT, (int) CreateWindowFlags.CW_USEDEFAULT, 42 | IntPtr.Zero, IntPtr.Zero, instanceHandle, IntPtr.Zero); 43 | 44 | if (hwnd == IntPtr.Zero) 45 | { 46 | Console.Error.WriteLine("window creation failed"); 47 | return -1; 48 | } 49 | 50 | User32Methods.ShowWindow(hwnd, ShowWindowCommands.SW_SHOWNORMAL); 51 | User32Methods.UpdateWindow(hwnd); 52 | 53 | Message msg; 54 | int res; 55 | while ((res = User32Methods.GetMessage(out msg, IntPtr.Zero, 0, 0)) != 0) 56 | { 57 | User32Methods.TranslateMessage(ref msg); 58 | User32Methods.DispatchMessage(ref msg); 59 | } 60 | 61 | return res; 62 | } 63 | 64 | private static IntPtr WindowProc(IntPtr hwnd, uint umsg, 65 | IntPtr wParam, IntPtr lParam) 66 | { 67 | var msg = (WM) umsg; 68 | switch (msg) 69 | { 70 | case WM.ERASEBKGND: 71 | return new IntPtr(1); 72 | case WM.CLOSE: 73 | { 74 | User32Methods.PostQuitMessage(0); 75 | break; 76 | } 77 | case WM.PAINT: 78 | { 79 | PaintStruct ps; 80 | var hdc = User32Methods.BeginPaint(hwnd, out ps); 81 | User32Methods.FillRect(hdc, ref ps.PaintRect, 82 | Gdi32Helpers.GetStockObject(StockObject.WHITE_BRUSH)); 83 | User32Methods.EndPaint(hwnd, ref ps); 84 | break; 85 | } 86 | } 87 | return User32Methods.DefWindowProc(hwnd, umsg, wParam, lParam); 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /Samples/Sample.Win32/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Sample.Win32")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Sample.Win32")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("2f8db172-d945-4551-b470-1835ab951ea3")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Samples/Sample.Win32/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Samples/Sample.Win32/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Samples/WinApi.TestGround/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Samples/WinApi.TestGround/DebugLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Linq; 4 | using System.Text; 5 | using Newtonsoft.Json; 6 | using WinApi.Desktop; 7 | 8 | namespace WinApi.TestGround 9 | { 10 | public sealed class DebugLogger 11 | { 12 | [Conditional("DEBUG")] 13 | private static void EnsureConsole() 14 | { 15 | ConsoleHelpers.EnsureConsole(); 16 | } 17 | 18 | [Conditional("DEBUG")] 19 | public static void Print(string format, params object[] o) 20 | { 21 | EnsureConsole(); 22 | var sb = new StringBuilder(); 23 | var serializedObjs = o.Select(x => JsonConvert.SerializeObject(x, Formatting.Indented)).ToArray(); 24 | sb.AppendFormat(format, serializedObjs); 25 | Console.WriteLine(sb.ToString()); 26 | } 27 | 28 | [Conditional("DEBUG")] 29 | public static void Print(string s) 30 | { 31 | EnsureConsole(); 32 | Console.WriteLine(s); 33 | } 34 | 35 | [Conditional("DEBUG")] 36 | public static void Print(object o) 37 | { 38 | EnsureConsole(); 39 | Console.WriteLine(JsonConvert.SerializeObject(o, Formatting.Indented)); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Samples/WinApi.TestGround/Program.cs: -------------------------------------------------------------------------------- 1 | using NetCoreEx.Geometry; 2 | using System; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using WinApi.Desktop; 6 | using WinApi.User32; 7 | using WinApi.Windows; 8 | using WinApi.Windows.Controls; 9 | using WinApi.Windows.Controls.Layouts; 10 | 11 | namespace WinApi.TestGround 12 | { 13 | class Program 14 | { 15 | static int Main(string[] args) 16 | { 17 | ApplicationHelpers.SetupDefaultExceptionHandlers(); 18 | try 19 | { 20 | var factory = WindowFactory.Create(); 21 | using (var win = factory.CreateWindow(() => new MainWindow(), 22 | "Hello", constructionParams: new FrameWindowConstructionParams())) 23 | { 24 | win.Show(); 25 | return new EventLoop().Run(win); 26 | } 27 | } 28 | catch (Exception ex) { 29 | ApplicationHelpers.ShowCriticalError(ex); 30 | } 31 | return 0; 32 | } 33 | 34 | public sealed class MainWindow : EventedWindowCore 35 | { 36 | private const int Iterations = 100_000; 37 | 38 | private readonly HorizontalStretchLayout m_layout = new HorizontalStretchLayout(); 39 | private bool m_done; 40 | private DateTime m_endTime; 41 | private DateTime m_startTime; 42 | private Task m_task; 43 | private StaticBox m_textBox1; 44 | private NativeWindow m_textBox2; 45 | private int m_times; 46 | 47 | protected override void OnCreate(ref CreateWindowPacket packet) 48 | { 49 | 50 | this.m_textBox1 = StaticBox.Create(hParent: this.Handle, 51 | styles: WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE, exStyles: 0); 52 | 53 | // You can use this to create the static box like this as well. 54 | // But there's rarely any performance benefit in doing so, and 55 | // this doesn't have a WindowProc that's connected. 56 | this.m_textBox2 = WindowFactory.CreateExternalWindow("static", hParent: this.Handle, 57 | styles: WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE, exStyles: 0); 58 | 59 | this.m_layout.ClientArea = this.GetClientRect(); 60 | this.m_layout.Margin = new Rectangle(10, 10, 10, 10); 61 | this.m_layout.Children.Add(this.m_textBox1); 62 | this.m_layout.Children.Add(this.m_textBox2); 63 | this.m_layout.PerformLayout(); 64 | 65 | var r = new Random(); 66 | 67 | this.m_task = Task.Run(() => 68 | { 69 | while (this.m_times < Iterations) 70 | { 71 | this.m_times++; 72 | this.SetPosition(50, 50, 1200 - r.Next(0, 1100), 900 - r.Next(0, 800)); 73 | } 74 | this.m_endTime = DateTime.Now; 75 | this.m_done = true; 76 | this.SetPosition(50, 50, 700, 500); 77 | }); 78 | this.m_startTime = DateTime.Now; 79 | base.OnCreate(ref packet); 80 | } 81 | 82 | protected override void OnSize(ref SizePacket packet) 83 | { 84 | var size = packet.Size; 85 | this.m_layout.SetSize(ref size); 86 | 87 | base.OnSize(ref packet); 88 | 89 | if (!this.m_done) return; 90 | 91 | var str = $"\r\n{DateTime.Now}: No. of changes done: {this.m_times}"; 92 | this.m_textBox1.SetText(str); 93 | 94 | var sb = new StringBuilder(); 95 | 96 | sb.AppendLine($"Start Time: {this.m_startTime}"); 97 | sb.AppendLine($"End Time: {this.m_endTime}"); 98 | sb.AppendLine(); 99 | 100 | if (this.m_endTime != DateTime.MinValue) sb.AppendLine($"Total Time: {this.m_endTime - this.m_startTime}"); 101 | this.m_textBox2.SetText(sb.ToString()); 102 | } 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /Samples/WinApi.TestGround/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Sample.Simple")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Sample.Simple")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("52271447-963c-4cca-8495-875aa61125ce")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Samples/WinApi.TestGround/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | 55 | true/pm 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Samples/WinApi.TestGround/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /WinApi.Desktop/ApplicationHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WinApi.Windows; 3 | 4 | namespace WinApi.Desktop 5 | { 6 | public static class ApplicationHelpers 7 | { 8 | static ApplicationHelpers() 9 | { 10 | DefaultUnhandledExceptionHandler = 11 | (sender, eventArgs) => 12 | { 13 | ShowCriticalError(eventArgs.ExceptionObject); 14 | if (eventArgs.IsTerminating) 15 | { 16 | ShowCriticalInfo( 17 | $"{Environment.NewLine}The application will now terminate. Press any key to do so."); 18 | Console.ReadKey(); 19 | } 20 | }; 21 | 22 | DefaultWindowExceptionHandler = ex => 23 | { 24 | ShowCriticalError(ex.InnerException); 25 | ex.SetHandled(); 26 | }; 27 | } 28 | 29 | public static WindowExceptionHandler DefaultWindowExceptionHandler { get; } 30 | public static UnhandledExceptionEventHandler DefaultUnhandledExceptionHandler { get; } 31 | 32 | public static void SetupDefaultExceptionHandlers() 33 | { 34 | AppDomain.CurrentDomain.UnhandledException += DefaultUnhandledExceptionHandler; 35 | WindowCore.UnhandledException += DefaultWindowExceptionHandler; 36 | } 37 | 38 | public static void ShowCriticalError(object exceptionObj, string message = null, string title = null) 39 | { 40 | const string defaultMessage = "Oh snap! Something went wrong."; 41 | if (message == null) message = defaultMessage; 42 | 43 | ConsoleHelpers.EnsureConsole(); 44 | if (!string.IsNullOrEmpty(title)) Console.Title = title; 45 | var exception = exceptionObj as Exception; 46 | string msg; 47 | if (exception != null) 48 | { 49 | msg = $"{Environment.NewLine}[CRITICAL] {message}{Environment.NewLine}{Environment.NewLine}" + 50 | $"{exception.Message}{Environment.NewLine}" + 51 | $"{exception.StackTrace}"; 52 | } 53 | else 54 | { 55 | msg = $"{Environment.NewLine}[CRITICAL] {message}{Environment.NewLine}{Environment.NewLine}" + 56 | $"{exceptionObj}{Environment.NewLine}"; 57 | } 58 | Console.Error.WriteLine(msg); 59 | } 60 | 61 | public static void ShowCriticalInfo(string message, string title = null, bool suffixNewLine = true) 62 | { 63 | ConsoleHelpers.EnsureConsole(); 64 | if (!string.IsNullOrEmpty(title)) Console.Title = title; 65 | if (suffixNewLine) Console.Error.WriteLine(message); 66 | else Console.Error.Write(message); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /WinApi.Desktop/ConsoleHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using WinApi.Kernel32; 4 | 5 | namespace WinApi.Desktop 6 | { 7 | public static class ConsoleHelpers 8 | { 9 | public static bool EnsureConsole() 10 | { 11 | if (Kernel32Methods.GetConsoleWindow() != IntPtr.Zero) return true; 12 | if (Kernel32Methods.AllocConsole()) return false; 13 | Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = true}); 14 | Console.SetError(new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = true}); 15 | Console.SetIn(new StreamReader(Console.OpenStandardInput())); 16 | return true; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /WinApi.Desktop/WinApi.Desktop.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | Prasanna V. Loganathar 5 | Prasanna V. Loganathar 6 | https://www.apache.org/licenses/LICENSE-2.0.txt 7 | https://github.com/prasannavl/WinApi 8 | https://github.com/prasannavl/WinApi 9 | https://raw.githubusercontent.com/prasannavl/WinApi/master/Misc/Logo.png 10 | Copyright © Prasanna V. Loganathar 11 | Desktop helpers for Win32 API with WinApi 12 | 4.0.0 13 | true 14 | win32 native interop desktop 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WinApi.DxUtils/Component/ComposedD3DComponent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct3D11; 4 | using WinApi.Core; 5 | using WinApi.DxUtils.Composition; 6 | using WinApi.DxUtils.Core; 7 | using WinApi.DxUtils.D3D11; 8 | using NetCoreEx.Geometry; 9 | 10 | namespace WinApi.DxUtils.Component 11 | { 12 | public class ComposedD3DComponent : IDisposable 13 | { 14 | public WindowSwapChainCompositor Compositor; 15 | public IntPtr Hwnd; 16 | private int m_compVariant; 17 | private ID3D11_1MetaResource m_d3D; 18 | public Size Size; 19 | 20 | public ID3D11MetaResourceCore D3D => this.m_d3D; 21 | 22 | public bool IsInitialized => this.m_d3D?.Device != null; 23 | 24 | public void Dispose() 25 | { 26 | DisposableHelpers.DisposeAndSetNull(ref this.Compositor); 27 | DisposableHelpers.DisposeAndSetNull(ref this.m_d3D); 28 | } 29 | 30 | public void Initialize(IntPtr hwnd, Size size, int directCompositionVariant = -1) 31 | { 32 | if (this.IsInitialized) this.Destroy(); 33 | this.Hwnd = hwnd; 34 | this.Size = size; 35 | this.m_compVariant = directCompositionVariant != -1 36 | ? directCompositionVariant 37 | : CompositionHelper.GetVariantForPlatform(); 38 | this.Create(); 39 | this.InitializeInternal(); 40 | } 41 | 42 | public void EnsureInitialized() 43 | { 44 | if (!this.IsInitialized) this.Initialize(this.Hwnd, this.Size, this.m_compVariant); 45 | } 46 | 47 | public void Resize(Size size) 48 | { 49 | if ((this.m_compVariant > 0) && ((size.Width <= 0) || (size.Height <= 0))) return; 50 | this.Size = size; 51 | this.m_d3D?.Resize(size); 52 | } 53 | 54 | private void InitializeInternal() 55 | { 56 | this.m_d3D.Initialize(this.Hwnd, this.Size); 57 | if (this.m_compVariant > 0) 58 | this.Compositor.Initialize(this.m_d3D, 59 | new WindowCompositorOptions(this.Hwnd)); 60 | } 61 | 62 | private void Create() 63 | { 64 | var d3dCreationFlags = DeviceCreationFlags.BgraSupport | DeviceCreationFlags.SingleThreaded; 65 | this.m_d3D = this.m_compVariant > 0 66 | ? D3D11MetaFactory.CreateForComposition(creationFlags: d3dCreationFlags) 67 | : D3D11MetaFactory.CreateForWindowTarget(creationFlags: d3dCreationFlags); 68 | this.Compositor = new WindowSwapChainCompositor(this.m_compVariant); 69 | } 70 | 71 | public bool PerformResetOnException(SharpDXException ex) 72 | { 73 | if (ErrorHelpers.ShouldResetDxgiForError(ex.Descriptor)) 74 | { 75 | this.m_d3D?.Destroy(); 76 | return true; 77 | } 78 | return false; 79 | } 80 | 81 | public void Destroy() 82 | { 83 | this.Compositor?.Destroy(); 84 | this.m_d3D?.Destroy(); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Component/Dx11Component.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct3D11; 4 | using WinApi.Core; 5 | using WinApi.DxUtils.Composition; 6 | using WinApi.DxUtils.Core; 7 | using WinApi.DxUtils.D2D1; 8 | using WinApi.DxUtils.D3D11; 9 | using Factory = SharpDX.DirectWrite.Factory; 10 | using FactoryType = SharpDX.DirectWrite.FactoryType; 11 | using NetCoreEx.Geometry; 12 | 13 | namespace WinApi.DxUtils.Component 14 | { 15 | public class Dx11Component : IDisposable 16 | { 17 | public WindowSwapChainCompositor Compositor; 18 | public IntPtr Hwnd; 19 | private int m_compVariant; 20 | private ID2D1_1MetaResource m_d2D; 21 | private ID3D11_1MetaResource m_d3D; 22 | private Factory m_dWriteFactory; 23 | public Size Size; 24 | 25 | public ID2D1_1MetaResourceCore D2D => this.m_d2D; 26 | public ID3D11MetaResourceCore D3D => this.m_d3D; 27 | public Factory TextFactory => this.m_dWriteFactory; 28 | 29 | public bool IsInitialized => this.m_d3D?.Device != null; 30 | 31 | public void Dispose() 32 | { 33 | DisposableHelpers.DisposeAndSetNull(ref this.Compositor); 34 | DisposableHelpers.DisposeAndSetNull(ref this.m_dWriteFactory); 35 | DisposableHelpers.DisposeAndSetNull(ref this.m_d2D); 36 | DisposableHelpers.DisposeAndSetNull(ref this.m_d3D); 37 | } 38 | 39 | public void Initialize(IntPtr hwnd, Size size, int directCompositionVariant = -1) 40 | { 41 | if (this.IsInitialized) this.Destroy(); 42 | this.Hwnd = hwnd; 43 | this.Size = size; 44 | this.m_compVariant = directCompositionVariant != -1 45 | ? directCompositionVariant 46 | : CompositionHelper.GetVariantForPlatform(); 47 | this.Create(); 48 | this.InitializeInternal(); 49 | } 50 | 51 | public void EnsureInitialized() 52 | { 53 | if (!this.IsInitialized) 54 | { 55 | this.Create(); 56 | this.InitializeInternal(); 57 | } 58 | } 59 | 60 | public void Resize(Size size) 61 | { 62 | if ((this.m_compVariant > 0) && ((size.Width <= 0) || (size.Height <= 0))) return; 63 | this.Size = size; 64 | this.m_d3D?.Resize(size); 65 | } 66 | 67 | private void InitializeInternal() 68 | { 69 | this.m_d3D.Initialize(this.Hwnd, this.Size); 70 | this.m_d2D.Initialize(this.m_d3D); 71 | if (this.m_compVariant > 0) 72 | this.Compositor.Initialize(this.m_d3D, 73 | new WindowCompositorOptions(this.Hwnd)); 74 | } 75 | 76 | private void Create() 77 | { 78 | var d3dCreationFlags = DeviceCreationFlags.BgraSupport | DeviceCreationFlags.SingleThreaded; 79 | this.m_d3D = this.m_compVariant > 0 80 | ? D3D11MetaFactory.CreateForComposition(creationFlags: d3dCreationFlags) 81 | : D3D11MetaFactory.CreateForWindowTarget(creationFlags: d3dCreationFlags); 82 | this.m_d2D = D2D1MetaFactory.CreateForSwapChain(); 83 | this.m_dWriteFactory = new Factory(FactoryType.Shared); 84 | this.Compositor = new WindowSwapChainCompositor(this.m_compVariant); 85 | } 86 | 87 | public bool PerformResetOnException(SharpDXException ex) 88 | { 89 | if (ErrorHelpers.ShouldResetDxgiForError(ex.Descriptor) 90 | || ErrorHelpers.ShouldResetD2DForError(ex.Descriptor)) 91 | { 92 | this.m_d3D?.Destroy(); 93 | return true; 94 | } 95 | return false; 96 | } 97 | 98 | public void Destroy() 99 | { 100 | this.Compositor?.Destroy(); 101 | this.m_d2D.Destroy(); 102 | this.m_d3D.Destroy(); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Composition/CompositionHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.DirectComposition; 4 | using SharpDX.DXGI; 5 | using WinApi.Core; 6 | using Device = SharpDX.DirectComposition.Device; 7 | using Surface = SharpDX.DirectComposition.Surface; 8 | 9 | namespace WinApi.DxUtils.Composition 10 | { 11 | public static class CompositionHelper 12 | { 13 | public static int GetVariantForPlatform(Version platformVersion = null) 14 | { 15 | if (platformVersion == null) platformVersion = VersionHelpers.GetWindowsVersion(); 16 | if (platformVersion.Major > 6) return 2; 17 | if (platformVersion.Major == 6) 18 | { 19 | if (platformVersion.Minor > 2) return 2; 20 | if (platformVersion.Minor > 1) return 1; 21 | } 22 | return 0; 23 | } 24 | 25 | public static ComObject CreateDevice(SharpDX.DXGI.Device dxgiDevice, int variant = -1) 26 | { 27 | if (variant == -1) variant = 2; 28 | if (variant > 1) { return new DesktopDevice(dxgiDevice); } 29 | return variant == 1 ? new Device(dxgiDevice) : null; 30 | } 31 | 32 | public static void Commit(ComObject device, int variant) 33 | { 34 | if (variant > 1) ((DesktopDevice) device).Commit(); 35 | else if (variant == 1) ((Device) device).Commit(); 36 | } 37 | 38 | public static Surface CreateSurface(ComObject device, int variant, int width, int height, Format pixelFormat, 39 | AlphaMode alphaMode) 40 | { 41 | if (variant > 1) { return new Surface((DesktopDevice) device, width, height, pixelFormat, alphaMode); } 42 | return variant == 1 ? new Surface((Device) device, width, height, pixelFormat, alphaMode) : null; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Composition/CompositorCore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.DirectComposition; 4 | using WinApi.DxUtils.Core; 5 | 6 | namespace WinApi.DxUtils.Composition 7 | { 8 | public abstract class CompositorCore : IDisposable, INotifyOnInitDestroy 9 | where TDxgiContainer : IDxgi1Container 10 | { 11 | private readonly Action m_onDxgiDestroyedAction; 12 | private readonly Action m_onDxgiInitializedAction; 13 | protected TDxgiContainer DxgiContainer; 14 | private ComObject m_device; 15 | private bool m_disposed; 16 | protected TOptions Options; 17 | 18 | protected CompositorCore(int variant) 19 | { 20 | if (variant == -1) variant = CompositionHelper.GetVariantForPlatform(); 21 | this.DeviceVariant = variant; 22 | this.m_onDxgiDestroyedAction = () => this.DestroyInternal(true); 23 | this.m_onDxgiInitializedAction = () => this.InitializeInternal(true); 24 | } 25 | 26 | public int DeviceVariant { get; } 27 | 28 | public ComObject Device { get { return this.m_device; } private set { this.m_device = value; } } 29 | 30 | public void Dispose() 31 | { 32 | this.m_disposed = true; 33 | GC.SuppressFinalize(this); 34 | this.Destroy(); 35 | } 36 | 37 | public event Action Initialized; 38 | public event Action Destroyed; 39 | 40 | private void CheckDisposed() 41 | { 42 | if (this.m_disposed) throw new ObjectDisposedException(this.GetType().Name); 43 | } 44 | 45 | ~CompositorCore() 46 | { 47 | this.Dispose(); 48 | } 49 | 50 | public void Destroy() 51 | { 52 | this.DestroyInternal(false); 53 | } 54 | 55 | public void Commit() 56 | { 57 | CompositionHelper.Commit(this.Device, this.DeviceVariant); 58 | } 59 | 60 | private void DestroyInternal(bool preserveDxgiSource) 61 | { 62 | if (!preserveDxgiSource) this.DisconnectFromDxgiSource(); 63 | this.DestroyResources(); 64 | DisposableHelpers.DisposeAndSetNull(ref this.m_device); 65 | this.Destroyed?.Invoke(); 66 | } 67 | 68 | protected void EnsureDevice() 69 | { 70 | if (this.Device == null) this.Device = CompositionHelper.CreateDevice(this.DxgiContainer.DxgiDevice, this.DeviceVariant); 71 | } 72 | 73 | public void Initialize(TDxgiContainer dxgiContainer, TOptions opts = default(TOptions)) 74 | { 75 | this.CheckDisposed(); 76 | if (this.Device != null) this.Destroy(); 77 | this.Options = opts; 78 | this.DxgiContainer = dxgiContainer; 79 | this.InitializeInternal(false); 80 | } 81 | 82 | private void InitializeInternal(bool dxgiSourcePreserved) 83 | { 84 | this.InitializeResources(); 85 | if (!dxgiSourcePreserved) this.ConnectToDxgiSource(); 86 | this.Initialized?.Invoke(); 87 | } 88 | 89 | protected abstract void InitializeResources(); 90 | 91 | protected abstract void DestroyResources(); 92 | 93 | private void ConnectToDxgiSource() 94 | { 95 | this.DxgiContainer.Destroyed += this.m_onDxgiDestroyedAction; 96 | this.DxgiContainer.Initialized += this.m_onDxgiInitializedAction; 97 | } 98 | 99 | private void DisconnectFromDxgiSource() 100 | { 101 | if (this.DxgiContainer == null) return; 102 | this.DxgiContainer.Initialized -= this.m_onDxgiInitializedAction; 103 | this.DxgiContainer.Destroyed -= this.m_onDxgiDestroyedAction; 104 | } 105 | 106 | public void EnsureInitialized() 107 | { 108 | this.CheckDisposed(); 109 | if (this.Device == null) this.InitializeInternal(true); 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Composition/WindowCompositor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | using SharpDX.DirectComposition; 5 | using SharpDX.DXGI; 6 | using WinApi.Core; 7 | using WinApi.DxUtils.Core; 8 | using AlphaMode = SharpDX.DXGI.AlphaMode; 9 | using Device = SharpDX.DirectComposition.Device; 10 | 11 | namespace WinApi.DxUtils.Composition 12 | { 13 | public class WindowCompositor : 14 | CompositorCore 15 | where TDxgiContainer : IDxgi1Container 16 | where TOptions : WindowCompositorOptions 17 | { 18 | private Target m_target; 19 | private Visual m_visual; 20 | public WindowCompositor(int variant = -1) : base(variant) {} 21 | 22 | public Target Target { get { return this.m_target; } private set { this.m_target = value; } } 23 | 24 | public Visual Visual { get { return this.m_visual; } private set { this.m_visual = value; } } 25 | 26 | protected override void InitializeResources() 27 | { 28 | this.EnsureDevice(); 29 | var opts = this.Options; 30 | if (this.DeviceVariant > 1) 31 | { 32 | var device = (DesktopDevice) this.Device; 33 | this.Target = Target.FromHwnd(device, opts.Hwnd, opts.IsTopMost); 34 | this.Visual = new Visual2(device); 35 | } 36 | if (this.DeviceVariant == 1) 37 | { 38 | var device = (Device) this.Device; 39 | this.Target = Target.FromHwnd(device, opts.Hwnd, opts.IsTopMost); 40 | this.Visual = new Visual(device); 41 | } 42 | } 43 | 44 | public void SetContent(ComObject rootContent) 45 | { 46 | if (this.Target != null) 47 | { 48 | this.Visual.Content = rootContent; 49 | this.Target.Root = this.Visual; 50 | } 51 | } 52 | 53 | protected override void DestroyResources() 54 | { 55 | DisposableHelpers.DisposeAndSetNull(ref this.m_visual); 56 | DisposableHelpers.DisposeAndSetNull(ref this.m_target); 57 | } 58 | } 59 | 60 | public class WindowSwapChainCompositor : WindowCompositor 61 | { 62 | public WindowSwapChainCompositor(int variant = -1) : base(variant) {} 63 | 64 | protected override void InitializeResources() 65 | { 66 | base.InitializeResources(); 67 | this.SetContent(this.DxgiContainer.SwapChain); 68 | this.Commit(); 69 | } 70 | } 71 | 72 | public class WindowCompositorOptions 73 | { 74 | public IntPtr Hwnd; 75 | public bool IsTopMost; 76 | 77 | public WindowCompositorOptions(IntPtr hwnd, bool isTopMost = false) 78 | { 79 | this.Hwnd = hwnd; 80 | this.IsTopMost = isTopMost; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Composition/WindowSurfaceCompositor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX.DirectComposition; 3 | using SharpDX.DXGI; 4 | using WinApi.Core; 5 | using WinApi.DxUtils.Core; 6 | using Device = SharpDX.DirectComposition.Device; 7 | using Surface = SharpDX.DirectComposition.Surface; 8 | using NetCoreEx.Geometry; 9 | 10 | namespace WinApi.DxUtils.Composition 11 | { 12 | public class WindowSurfaceCompositor : WindowCompositor 13 | { 14 | private Surface m_surface; 15 | public WindowSurfaceCompositor(int variant = -1) : base(variant) {} 16 | 17 | public Surface Surface { get { return this.m_surface; } set { this.m_surface = value; } } 18 | 19 | public Size Size { get { return this.Options.Size; } set { this.Options.Size = value; } } 20 | 21 | public void EnsureInitialized(Size size) 22 | { 23 | this.EnsureInitialized(); 24 | if (this.Size != size) this.Resize(size); 25 | } 26 | 27 | protected override void InitializeResources() 28 | { 29 | base.InitializeResources(); 30 | this.CreateSurface(); 31 | } 32 | 33 | public void Resize(Size size) 34 | { 35 | if (this.Options.Size != size) 36 | { 37 | this.Options.Size = size; 38 | this.DestroySurface(); 39 | this.CreateSurface(); 40 | } 41 | } 42 | 43 | private void CreateSurface() 44 | { 45 | var size = this.Options.Size; 46 | this.Surface = CompositionHelper.CreateSurface(this.Device, this.DeviceVariant, size.Width, size.Height, 47 | this.Options.PixelFormat, this.Options.AlphaMode); 48 | this.SetContent(this.Surface); 49 | } 50 | 51 | private void DestroySurface() 52 | { 53 | DisposableHelpers.DisposeAndSetNull(ref this.m_surface); 54 | } 55 | 56 | protected override void DestroyResources() 57 | { 58 | this.DestroySurface(); 59 | base.DestroyResources(); 60 | } 61 | } 62 | 63 | public class WindowSurfaceCompositorOptions : WindowCompositorOptions 64 | { 65 | public AlphaMode AlphaMode; 66 | public Format PixelFormat; 67 | 68 | public Size Size; 69 | 70 | public WindowSurfaceCompositorOptions(IntPtr hwnd, Size size, Format format, AlphaMode mode, 71 | bool isTopMost = false) : base(hwnd, isTopMost) 72 | { 73 | this.Size = size; 74 | this.PixelFormat = format; 75 | this.AlphaMode = mode; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Core/DxgiContainerBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SharpDX.DXGI; 5 | 6 | namespace WinApi.DxUtils.Core 7 | { 8 | public abstract class DxgiContainerBase 9 | { 10 | private List m_connectedResources; 11 | 12 | protected List LinkedResources 13 | { 14 | get { return this.m_connectedResources ?? (this.m_connectedResources = new List()); } 15 | set { this.m_connectedResources = value; } 16 | } 17 | 18 | public event Action Initialized; 19 | public event Action Destroyed; 20 | 21 | protected void InvokeInitializedEvent() 22 | { 23 | this.Initialized?.Invoke(); 24 | } 25 | 26 | protected void InvokeDestroyedEvent() 27 | { 28 | this.Destroyed?.Invoke(); 29 | } 30 | 31 | public void AddLinkedResource(IDxgiConnectable resource) 32 | { 33 | if (this.LinkedResources.Contains(resource)) return; 34 | this.LinkedResources.Add(resource); 35 | } 36 | 37 | public void AddLinkedResources(IEnumerable resources) 38 | { 39 | this.LinkedResources.AddRange(resources.Except(this.LinkedResources)); 40 | } 41 | 42 | public void RemoveLinkedResource(IDxgiConnectable resource) 43 | { 44 | this.LinkedResources.Remove(resource); 45 | } 46 | 47 | public void RemoveLinkedResources(IEnumerable resources) 48 | { 49 | foreach (var res in resources) { this.LinkedResources.Remove(res); } 50 | } 51 | 52 | protected void DisconnectLinkedResources() 53 | { 54 | foreach (var res in this.LinkedResources) { res.DisconnectFromDxgi(); } 55 | } 56 | 57 | protected void ConnectLinkedResources() 58 | { 59 | foreach (var res in this.LinkedResources) { res.ConnectToDxgi(); } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Core/Interfaces.cs: -------------------------------------------------------------------------------- 1 | using NetCoreEx.Geometry; 2 | using System; 3 | using System.Collections.Generic; 4 | using WinApi.Core; 5 | 6 | namespace WinApi.DxUtils.Core 7 | { 8 | public interface IDxgi1 9 | { 10 | SharpDX.DXGI.Device DxgiDevice { get; } 11 | SharpDX.DXGI.Factory DxgiFactory { get; } 12 | SharpDX.DXGI.Adapter Adapter { get; } 13 | } 14 | 15 | public interface IDxgi1WithSwapChain : IDxgi1 16 | { 17 | SharpDX.DXGI.SwapChain SwapChain { get; } 18 | } 19 | 20 | // ReSharper disable once InconsistentNaming 21 | public interface IDxgi1_2 22 | { 23 | SharpDX.DXGI.Device2 DxgiDevice2 { get; } 24 | SharpDX.DXGI.Factory2 DxgiFactory2 { get; } 25 | } 26 | 27 | // ReSharper disable once InconsistentNaming 28 | public interface IDxgi1_2WithSwapChain : IDxgi1_2 29 | { 30 | SharpDX.DXGI.SwapChain1 SwapChain1 { get; } 31 | } 32 | 33 | public interface IDxgi1Container : IDxgiContainerCore, IDxgi1, INotifyOnInitDestroy {} 34 | 35 | public interface IDxgi1ContainerWithSwapChain : IDxgi1Container, IDxgi1WithSwapChain {} 36 | 37 | 38 | // ReSharper disable once InconsistentNaming 39 | public interface IDxgi1_2Container : IDxgi1Container, IDxgi1_2 {} 40 | 41 | // ReSharper disable once InconsistentNaming 42 | public interface IDxgi1_2ContainerWithSwapChain : IDxgi1ContainerWithSwapChain, IDxgi1_2WithSwapChain {} 43 | 44 | 45 | public interface IDxgi1MetaResource : IDxgi1Container 46 | { 47 | void Initialize(); 48 | void EnsureInitialized(); 49 | void Destroy(); 50 | } 51 | 52 | public interface ID3D11MetaResourceCore : IDxgi1ContainerWithSwapChain, IDisposable 53 | { 54 | SharpDX.Direct3D11.Device Device { get; } 55 | SharpDX.Direct3D11.DeviceContext Context { get; } 56 | SharpDX.Direct3D11.RenderTargetView RenderTargetView { get; } 57 | } 58 | 59 | // ReSharper disable once InconsistentNaming 60 | public interface ID3D11_1MetaResourceCore : ID3D11MetaResourceCore, IDxgi1_2ContainerWithSwapChain {} 61 | 62 | public interface ID3D11MetaResource : ID3D11MetaResourceCore 63 | { 64 | void Initialize(IntPtr hwnd, Size size); 65 | void EnsureInitialized(); 66 | void Resize(Size size); 67 | void Destroy(); 68 | } 69 | 70 | // ReSharper disable once InconsistentNaming 71 | public interface ID3D11_1MetaResource : ID3D11MetaResource, ID3D11_1MetaResourceCore {} 72 | 73 | // ReSharper disable once InconsistentNaming 74 | public interface ID2D1_1MetaResourceCore : IDxgiConnectable, INotifyOnInitDestroy, IDisposable 75 | { 76 | SharpDX.Direct2D1.Device Device { get; } 77 | SharpDX.Direct2D1.DeviceContext Context { get; } 78 | SharpDX.Direct2D1.Factory1 Factory1 { get; } 79 | } 80 | 81 | // ReSharper disable once InconsistentNaming 82 | public interface ID2D1_1MetaResource : ID2D1_1MetaResourceCore 83 | { 84 | void Initialize(TDxgi1Container dxgiContainer, bool autoLink = true); 85 | void EnsureInitialized(); 86 | void Destroy(); 87 | } 88 | 89 | public interface IDxgiContainerCore 90 | { 91 | void AddLinkedResource(IDxgiConnectable resource); 92 | void AddLinkedResources(IEnumerable resources); 93 | void RemoveLinkedResource(IDxgiConnectable resource); 94 | void RemoveLinkedResources(IEnumerable resources); 95 | } 96 | 97 | public interface IDxgiConnectable 98 | { 99 | void ConnectToDxgi(); 100 | void DisconnectFromDxgi(); 101 | } 102 | 103 | public interface INotifyOnInitDestroy 104 | { 105 | event Action Initialized; 106 | event Action Destroyed; 107 | } 108 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/D2D1/D2D1Helper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX.Direct2D1; 3 | using SharpDX.DXGI; 4 | using WinApi.DxUtils.Core; 5 | 6 | namespace WinApi.DxUtils.D2D1 7 | { 8 | public static class D2D1Helper 9 | { 10 | public static void ConnectContextToDxgiSwapChain( 11 | D2D1MetaResource d2D1MetaResource) 12 | { 13 | using (var surface = d2D1MetaResource.DxgiContainer.SwapChain1.GetBackBuffer(0)) 14 | { 15 | using (var bitmap = new Bitmap1(d2D1MetaResource.Context, surface)) d2D1MetaResource.Context.Target = bitmap; 16 | } 17 | } 18 | 19 | public static void DisconnectContextFromDxgiSwapChain( 20 | D2D1MetaResource d2D1MetaResource) 21 | { 22 | var currentTarget = d2D1MetaResource.Context?.Target; 23 | if (currentTarget == null) return; 24 | currentTarget.Dispose(); 25 | d2D1MetaResource.Context.Target = null; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/D2D1/D2D1MetaFactory.cs: -------------------------------------------------------------------------------- 1 | using SharpDX.Direct2D1; 2 | using WinApi.DxUtils.Core; 3 | 4 | namespace WinApi.DxUtils.D2D1 5 | { 6 | public class D2D1MetaFactory 7 | { 8 | public static D2D1MetaResource Create(ref CreationProperties props) 9 | { 10 | return CreateCore(ref props); 11 | } 12 | 13 | public static D2D1MetaResource Create( 14 | ThreadingMode threadingMode = ThreadingMode.SingleThreaded, 15 | DeviceContextOptions contextOptions = DeviceContextOptions.EnableMultithreadedOptimizations, 16 | DebugLevel debugLevel = DebugLevel.None) 17 | { 18 | var props = new CreationProperties 19 | { 20 | DebugLevel = debugLevel, 21 | ThreadingMode = threadingMode, 22 | Options = contextOptions 23 | }; 24 | return CreateCore(ref props); 25 | } 26 | 27 | private static D2D1MetaResource CreateCore( 28 | ref CreationProperties props) 29 | { 30 | #if DEBUG 31 | // Note: These have no impact on solution outside 32 | // of this project. This is only for internal testing 33 | // purposes 34 | if (props.DebugLevel == 0) props.DebugLevel = DebugLevel.Information; 35 | #endif 36 | return new D2D1MetaResource(props, null, null); 37 | } 38 | 39 | public static D2D1MetaResource CreateForSwapChain(ref CreationProperties props) 40 | { 41 | return CreateForSwapChainCore(ref props); 42 | } 43 | 44 | public static D2D1MetaResource CreateForSwapChain( 45 | ThreadingMode threadingMode = ThreadingMode.SingleThreaded, 46 | DeviceContextOptions contextOptions = DeviceContextOptions.EnableMultithreadedOptimizations, 47 | DebugLevel debugLevel = DebugLevel.None) 48 | { 49 | var props = new CreationProperties 50 | { 51 | DebugLevel = debugLevel, 52 | ThreadingMode = threadingMode, 53 | Options = contextOptions 54 | }; 55 | return CreateForSwapChainCore(ref props); 56 | } 57 | 58 | private static D2D1MetaResource CreateForSwapChainCore( 59 | ref CreationProperties props) 60 | { 61 | #if DEBUG 62 | // Note: These have no impact on solution outside 63 | // of this project. This is only for internal testing 64 | // purposes 65 | if (props.DebugLevel == 0) props.DebugLevel = DebugLevel.Information; 66 | #endif 67 | return new D2D1MetaResource(props, D2D1Helper.ConnectContextToDxgiSwapChain, 68 | D2D1Helper.DisconnectContextFromDxgiSwapChain); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/D3D11/D3D11Container.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX.Direct3D; 3 | using SharpDX.Direct3D11; 4 | using SharpDX.DXGI; 5 | using SharpDX.Mathematics.Interop; 6 | using WinApi.Core; 7 | using WinApi.DxUtils.Core; 8 | using Device = SharpDX.Direct3D11.Device; 9 | using NetCoreEx.Geometry; 10 | 11 | namespace WinApi.DxUtils.D3D11 12 | { 13 | public abstract class D3D11ContainerCore : D3D11Dxgi1_2ContainerCore, IDxgi1ContainerWithSwapChain 14 | { 15 | public virtual DeviceContext Context { get; protected set; } 16 | public virtual RenderTargetView RenderTargetView { get; protected set; } 17 | public virtual SwapChain SwapChain { get; protected set; } 18 | 19 | public static Size GetValidatedSize(ref Size size) 20 | { 21 | var h = size.Height >= 0 ? size.Height : 0; 22 | var w = size.Width >= 0 ? size.Width : 0; 23 | return new Size(w, h); 24 | } 25 | 26 | protected void EnsureSwapChain() 27 | { 28 | if (this.SwapChain == null) this.CreateSwapChain(); 29 | } 30 | 31 | protected abstract void CreateSwapChain(); 32 | 33 | protected void EnsureContext() 34 | { 35 | if (this.Context == null) this.CreateContext(); 36 | } 37 | 38 | protected abstract void CreateContext(); 39 | 40 | protected void EnsureRenderTargetView() 41 | { 42 | if (this.RenderTargetView == null) this.CreateRenderTargetView(); 43 | } 44 | 45 | protected abstract void CreateRenderTargetView(); 46 | } 47 | 48 | // ReSharper disable once InconsistentNaming 49 | public abstract class D3D11_1ContainerCore : D3D11ContainerCore, IDxgi1_2ContainerWithSwapChain 50 | { 51 | public override DeviceContext Context => this.Context1; 52 | 53 | public virtual DeviceContext1 Context1 { get; protected set; } 54 | public override Factory DxgiFactory => this.DxgiFactory2; 55 | public override SharpDX.DXGI.Device DxgiDevice => this.DxgiDevice2; 56 | public override SwapChain SwapChain => this.SwapChain1; 57 | public virtual SwapChain1 SwapChain1 { get; protected set; } 58 | } 59 | 60 | // ReSharper disable once InconsistentNaming 61 | public abstract class D3D11_1Container : D3D11_1ContainerCore 62 | { 63 | protected override void CreateDxgiDevice() 64 | { 65 | this.EnsureDevice(); 66 | this.DxgiDevice2 = this.Device1.QueryInterface(); 67 | } 68 | 69 | protected override void CreateAdapter() 70 | { 71 | this.EnsureDxgiDevice(); 72 | this.Adapter = this.DxgiDevice2.GetParent(); 73 | } 74 | 75 | protected override void CreateDxgiFactory() 76 | { 77 | this.EnsureAdapter(); 78 | this.DxgiFactory2 = this.Adapter.GetParent(); 79 | } 80 | 81 | protected override void CreateContext() 82 | { 83 | this.EnsureDevice(); 84 | this.Context1 = this.Device1.ImmediateContext1; 85 | } 86 | 87 | protected override void CreateRenderTargetView() 88 | { 89 | this.EnsureDevice(); 90 | this.EnsureSwapChain(); 91 | using (var backBuffer = this.SwapChain1.GetBackBuffer(0)) { 92 | this.RenderTargetView = new RenderTargetView(this.Device1, backBuffer); 93 | } 94 | } 95 | 96 | protected void ConnectRenderTargetView() 97 | { 98 | this.EnsureContext(); 99 | this.EnsureRenderTargetView(); 100 | this.Context1.OutputMerger.SetRenderTargets(this.RenderTargetView); 101 | } 102 | 103 | protected void DisconnectRenderTargetView() 104 | { 105 | if (this.Context == null) return; 106 | this.Context1.OutputMerger.SetRenderTargets((RenderTargetView) null); 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/D3D11/D3D11Dxgi1_2MetaResource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX.DXGI; 3 | using WinApi.DxUtils.Core; 4 | using Device1 = SharpDX.Direct3D11.Device1; 5 | 6 | namespace WinApi.DxUtils.D3D11 7 | { 8 | // ReSharper disable once InconsistentNaming 9 | public class D3D11Dxgi1_2MetaResource : D3D11Dxgi1_2ContainerCore, IDxgi1MetaResource 10 | { 11 | private readonly D3D11DxgiOptions m_opts; 12 | private Adapter m_adapter; 13 | private Device1 m_device; 14 | private Device2 m_dxgiDevice; 15 | private Factory2 m_dxgiFactory; 16 | private bool m_isDisposed; 17 | 18 | public D3D11Dxgi1_2MetaResource(D3D11DxgiOptions opts) 19 | { 20 | this.m_opts = opts; 21 | } 22 | 23 | public override Device1 Device1 { get { return this.m_device; } protected set { this.m_device = value; } } 24 | 25 | public override Device2 DxgiDevice2 26 | { 27 | get { return this.m_dxgiDevice; } 28 | protected set { this.m_dxgiDevice = value; } 29 | } 30 | 31 | public override Factory2 DxgiFactory2 32 | { 33 | get { return this.m_dxgiFactory; } 34 | protected set { this.m_dxgiFactory = value; } 35 | } 36 | 37 | public override Adapter Adapter { get { return this.m_adapter; } protected set { this.m_adapter = value; } } 38 | 39 | public void Initialize() 40 | { 41 | this.CheckDisposed(); 42 | if (this.Device1 != null) this.Destroy(); 43 | this.InitializeInternal(); 44 | } 45 | 46 | public void EnsureInitialized() 47 | { 48 | this.CheckDisposed(); 49 | if (this.Device1 == null) this.InitializeInternal(); 50 | } 51 | 52 | public void Destroy() 53 | { 54 | this.DisconnectLinkedResources(); 55 | DisposableHelpers.DisposeAndSetNull(ref this.m_dxgiFactory); 56 | DisposableHelpers.DisposeAndSetNull(ref this.m_adapter); 57 | DisposableHelpers.DisposeAndSetNull(ref this.m_dxgiDevice); 58 | DisposableHelpers.DisposeAndSetNull(ref this.m_device); 59 | this.InvokeDestroyedEvent(); 60 | } 61 | 62 | protected override void CreateDxgiDevice() 63 | { 64 | this.EnsureDevice(); 65 | this.DxgiDevice2 = this.Device1.QueryInterface(); 66 | } 67 | 68 | protected override void CreateAdapter() 69 | { 70 | this.EnsureDxgiDevice(); 71 | this.Adapter = this.DxgiDevice2.GetParent(); 72 | } 73 | 74 | protected override void CreateDxgiFactory() 75 | { 76 | this.EnsureAdapter(); 77 | this.DxgiFactory2 = this.Adapter.GetParent(); 78 | } 79 | 80 | protected override void CreateDevice() 81 | { 82 | this.Device1 = D3D11MetaFactory.CreateD3DDevice1(this.m_opts); 83 | } 84 | 85 | private void InitializeInternal() 86 | { 87 | this.EnsureDxgiDevice(); 88 | this.InvokeInitializedEvent(); 89 | } 90 | 91 | public void Dispose() 92 | { 93 | this.m_isDisposed = true; 94 | GC.SuppressFinalize(this); 95 | this.Destroy(); 96 | this.LinkedResources.Clear(); 97 | } 98 | 99 | ~D3D11Dxgi1_2MetaResource() 100 | { 101 | this.Dispose(); 102 | } 103 | 104 | private void CheckDisposed() 105 | { 106 | if (this.m_isDisposed) throw new ObjectDisposedException(nameof(D3D11Dxgi1_2MetaResource)); 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/D3D11/D3D11DxgiContainer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using SharpDX.Direct3D; 6 | using SharpDX.Direct3D11; 7 | using SharpDX.DXGI; 8 | using WinApi.DxUtils.Core; 9 | using Device = SharpDX.Direct3D11.Device; 10 | using Device1 = SharpDX.Direct3D11.Device1; 11 | 12 | namespace WinApi.DxUtils.D3D11 13 | { 14 | public abstract class D3D11Dxgi1ContainerCore : DxgiContainerBase, IDxgi1Container 15 | { 16 | public virtual Device Device { get; protected set; } 17 | public virtual SharpDX.DXGI.Device DxgiDevice { get; protected set; } 18 | public virtual Factory DxgiFactory { get; protected set; } 19 | public virtual Adapter Adapter { get; protected set; } 20 | 21 | protected void EnsureDxgiDevice() 22 | { 23 | if (this.DxgiDevice == null) this.CreateDxgiDevice(); 24 | } 25 | 26 | protected abstract void CreateDxgiDevice(); 27 | 28 | protected void EnsureAdapter() 29 | { 30 | if (this.Adapter == null) this.CreateAdapter(); 31 | } 32 | 33 | protected abstract void CreateAdapter(); 34 | 35 | protected void EnsureDxgiFactory() 36 | { 37 | if (this.DxgiFactory == null) this.CreateDxgiFactory(); 38 | } 39 | 40 | protected abstract void CreateDxgiFactory(); 41 | 42 | protected void EnsureDevice() 43 | { 44 | if (this.Device == null) this.CreateDevice(); 45 | } 46 | 47 | protected abstract void CreateDevice(); 48 | } 49 | 50 | // ReSharper disable once InconsistentNaming 51 | public abstract class D3D11Dxgi1_2ContainerCore : D3D11Dxgi1ContainerCore, IDxgi1_2Container 52 | { 53 | public override Device Device => this.Device1; 54 | public virtual Device1 Device1 { get; protected set; } 55 | public override Factory DxgiFactory => this.DxgiFactory2; 56 | public override SharpDX.DXGI.Device DxgiDevice => this.DxgiDevice2; 57 | 58 | public virtual Factory2 DxgiFactory2 { get; protected set; } 59 | public virtual SharpDX.DXGI.Device2 DxgiDevice2 { get; protected set; } 60 | } 61 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/DxPainter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SharpDX; 7 | using SharpDX.Direct2D1; 8 | using SharpDX.Mathematics.Interop; 9 | using WinApi.DxUtils.Component; 10 | using WinApi.Windows; 11 | 12 | namespace WinApi.DxUtils 13 | { 14 | public static class DxPainter 15 | { 16 | public static void HandlePaint(EventedWindowCore window, Dx11Component resource, 17 | Action handler) 18 | { 19 | resource.EnsureInitialized(); 20 | try 21 | { 22 | handler(resource); 23 | resource.D3D.SwapChain.Present(1, 0); 24 | window.Validate(); 25 | } 26 | catch (SharpDXException ex) 27 | { 28 | if (!resource.PerformResetOnException(ex)) throw; 29 | } 30 | } 31 | 32 | public static void HandlePaintD2D(EventedWindowCore window, Dx11Component resource, 33 | Action handler) 34 | { 35 | resource.EnsureInitialized(); 36 | try 37 | { 38 | var context = resource.D2D.Context; 39 | context.BeginDraw(); 40 | handler(context); 41 | context.EndDraw(); 42 | resource.D3D.SwapChain.Present(1, 0); 43 | window.Validate(); 44 | } 45 | catch (SharpDXException ex) 46 | { 47 | if (!resource.PerformResetOnException(ex)) throw; 48 | } 49 | } 50 | 51 | public static void HandlePaintD2DClipped(EventedWindowCore window, Dx11Component resource, 52 | Action handler, RawRectangleF clip, RawColor4? clearColorBeforeClip = null) 53 | { 54 | HandlePaintD2DClipped(window, resource, handler, ref clip, clearColorBeforeClip); 55 | } 56 | 57 | public static void HandlePaintD2DClipped(EventedWindowCore window, Dx11Component resource, 58 | Action handler, ref RawRectangleF clip, RawColor4? clearColorBeforeClip = null) 59 | { 60 | resource.EnsureInitialized(); 61 | try 62 | { 63 | var context = resource.D2D.Context; 64 | context.BeginDraw(); 65 | if (clearColorBeforeClip.HasValue) context.Clear(clearColorBeforeClip.Value); 66 | context.PushAxisAlignedClip(clip, 67 | AntialiasMode.Aliased); 68 | handler(context); 69 | context.PopAxisAlignedClip(); 70 | context.EndDraw(); 71 | resource.D3D.SwapChain.Present(1, 0); 72 | window.Validate(); 73 | } 74 | catch (SharpDXException ex) 75 | { 76 | if (!resource.PerformResetOnException(ex)) throw; 77 | } 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/DxVersionInfo.txt: -------------------------------------------------------------------------------- 1 |  2 | /** 3 | * DX Common Interface Versions: 4 | * 5 | * DXGI: 6 | * ==== 7 | * Platforms: 8 | * ---- 9 | * v1.0 - 1.1 : Win 7+ 10 | * v1.2: Win 7 (Platform Update)+, Win 8+ 11 | * v1.3: Win 8.1+ 12 | * v1.4: Win 10+ 13 | * v1.5: Win 10 (2016 Anniversary Update)+ 14 | * ---- 15 | * 16 | * v1.0: Factory, Adapter, Device, SwapChain, Output, Resource, Surface 17 | * v1.1: Factory1, Adapter1, Device1, Surface1 18 | * v1.2: Factory2, Adapter2, SwapChain1, Device2, Debug, Output1, Resource1, Surface2 19 | * v1.3: Factory3, Adapter3, SwapChain2, Device3, Debug1, Output2, Output3 20 | * v1.4: Factory4, SwapChain3, Output4 21 | * v1.5: Factory5, Device4, SwapChain4, Output5 22 | * 23 | * D3D11: 24 | * ==== 25 | * Platforms: 26 | * ---- 27 | * v11 - Windows 7+ 28 | * v11.1 - Win 7 (Platform Update)+, Win 8+ 29 | * v11.2 - Win 8.1+ 30 | * v11.3, v12 - Win 10+ 31 | * ---- 32 | * 33 | * v11 - Device, DeviceContext 34 | * v11.1 - Device1, DeviceContext1 35 | * v11.2 - Device2, DeviceContext2 36 | * v11.3 - Device3, DeviceContext3 37 | * v11.4 - Device4 38 | */ 39 | 40 | 41 | /** 42 | * D2D Common Interfaces: 43 | * ==== 44 | * Platforms: 45 | * ---- 46 | * v1.0 - Win 7+ 47 | * v1.1 - Win 7 (Platform Update)+, Win 8+ 48 | * v1.2 - Win 8.1+ 49 | * v1.3 - Win 10+ 50 | * ---- 51 | * 52 | * v1.0 - Factory, Bitmap, BitmapBrush 53 | * v1.1 - Factory1, Device, DeviceContext, Bitmap1, BitmapBrush1 54 | * v1.2 - Factory2, Device1, DeviceContext1 55 | * v1.3 - Factory3, Factory4, Factory5, Device2, Device3, Device4, DeviceContext2, DeviceContext3, DeviceContext4 56 | * 57 | */ 58 | 59 | 60 | /** 61 | * DirectWrite Interfaces: 62 | * ==== 63 | * Platforms: 64 | * ---- 65 | * v1.0 - Win 7+ 66 | * v1.1 - Win 8+ 67 | * v1.2 - Win 8.1+ 68 | * v1.3 - Win 10+ 69 | * ---- 70 | */ 71 | 72 | 73 | /** 74 | * DirectComposition Interfaces: 75 | * ==== 76 | * Platforms: 77 | * ---- 78 | * v1.0 - Win 8+ 79 | * v1.1 - Win 8.1+ 80 | * ---- 81 | */ 82 | -------------------------------------------------------------------------------- /WinApi.DxUtils/DxWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SharpDX.Direct2D1; 7 | using SharpDX.Mathematics.Interop; 8 | using WinApi.Core; 9 | using WinApi.DxUtils.Component; 10 | using WinApi.User32; 11 | using WinApi.Windows; 12 | 13 | namespace WinApi.DxUtils 14 | { 15 | public class DxWindow : EventedWindowCore 16 | { 17 | protected readonly Dx11Component Dx = new Dx11Component(); 18 | 19 | private bool m_isFirstBkgdErased; 20 | 21 | protected override void OnCreate(ref CreateWindowPacket packet) 22 | { 23 | this.Dx.Initialize(this.Handle, this.GetClientSize()); 24 | base.OnCreate(ref packet); 25 | } 26 | 27 | protected virtual void OnDxPaint(Dx11Component resource) {} 28 | 29 | protected override void OnPaint(ref PaintPacket packet) 30 | { 31 | DxPainter.HandlePaint(this, this.Dx, this.OnDxPaint); 32 | } 33 | 34 | protected override void OnSize(ref SizePacket packet) 35 | { 36 | this.Dx.Resize(packet.Size); 37 | base.OnSize(ref packet); 38 | } 39 | 40 | protected override void OnEraseBkgnd(ref EraseBkgndPacket packet) 41 | { 42 | if (this.m_isFirstBkgdErased) 43 | { 44 | packet.Result = EraseBackgroundResult.DisableDefaultErase; 45 | return; 46 | } 47 | this.m_isFirstBkgdErased = true; 48 | base.OnEraseBkgnd(ref packet); 49 | } 50 | 51 | protected override void Dispose(bool disposing) 52 | { 53 | this.Dx.Dispose(); 54 | base.Dispose(disposing); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using WinApi.DxUtils.Core; 4 | 5 | namespace WinApi.DxUtils 6 | { 7 | public static class DisposableHelpers 8 | { 9 | public static void DisposeAndSetNull(ref T obj) 10 | where T : class, IDisposable 11 | { 12 | if (obj != null) 13 | { 14 | obj.Dispose(); 15 | obj = null; 16 | } 17 | } 18 | } 19 | 20 | public static class ErrorHelpers 21 | { 22 | public static bool ShouldResetDxgiForError(ResultDescriptor resultDescriptor) 23 | { 24 | return ShouldResetDxgiForError(resultDescriptor.Code); 25 | } 26 | 27 | public static bool ShouldResetDxgiForError(int code) 28 | { 29 | return (code == SharpDX.DXGI.ResultCode.DeviceRemoved.Code) || 30 | (code == SharpDX.DXGI.ResultCode.DeviceReset.Code); 31 | } 32 | 33 | public static bool ShouldResetD2DForError(ResultDescriptor resultDescriptor) 34 | { 35 | return ShouldResetD2DForError(resultDescriptor.Code); 36 | } 37 | 38 | public static bool ShouldResetD2DForError(int code) 39 | { 40 | return code == SharpDX.Direct2D1.ResultCode.RecreateTarget.Code; 41 | } 42 | } 43 | 44 | internal static class VersionHelpers { 45 | public static Version GetWindowsVersion() 46 | { 47 | var desc = System.Runtime.InteropServices.RuntimeInformation.OSDescription; 48 | if (desc.Contains(" 10.")) 49 | { 50 | return new Version(10, 0, 0, 0); 51 | } 52 | else if (desc.Contains(" 6.3")) 53 | { 54 | return new Version(6, 3, 0, 0); 55 | } 56 | else if (desc.Contains(" 6.2")) 57 | { 58 | return new Version(6, 2, 0, 0); 59 | } 60 | return new Version(6, 1, 0, 0); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /WinApi.DxUtils/WinApi.DxUtils.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard1.4 4 | Prasanna V. Loganathar 5 | Prasanna V. Loganathar 6 | https://www.apache.org/licenses/LICENSE-2.0.txt 7 | https://github.com/prasannavl/WinApi 8 | https://github.com/prasannavl/WinApi 9 | https://raw.githubusercontent.com/prasannavl/WinApi/master/Misc/Logo.png 10 | Copyright © Prasanna V. Loganathar 11 | DirectX helpers and utils to ease directx version management with SharpDx and WinApi. 12 | 4.0.0 13 | true 14 | directx d3d utils win32 native interop 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /WinApi.Utils/DwmWindow.cs: -------------------------------------------------------------------------------- 1 | using NetCoreEx.Geometry; 2 | using System; 3 | using WinApi.Core; 4 | using WinApi.DwmApi; 5 | using WinApi.User32; 6 | using WinApi.User32.Experimental; 7 | using WinApi.UxTheme; 8 | using WinApi.Windows; 9 | using WinApi.Windows.Helpers; 10 | 11 | namespace WinApi.Utils 12 | { 13 | public class DwmWindow : EventedWindowCore 14 | { 15 | protected readonly DwmWindowHelper DwmHelper; 16 | 17 | public DwmWindow() 18 | { 19 | this.DwmHelper = new DwmWindowHelper(this); 20 | } 21 | 22 | protected bool DrawCaptionIcon { get; set; } 23 | protected bool DrawCaptionTitle { get; set; } 24 | protected bool AllowSystemMenu { get; set; } 25 | 26 | protected override void OnCreate(ref CreateWindowPacket packet) 27 | { 28 | this.DwmHelper.Initialize(this.DrawCaptionIcon, this.DrawCaptionTitle, this.AllowSystemMenu); 29 | base.OnCreate(ref packet); 30 | } 31 | 32 | public override void ClientToScreen(ref Rectangle clientRect, out Rectangle screenRect) 33 | { 34 | base.ClientToScreen(ref clientRect, out screenRect); 35 | screenRect.Top += -this.DwmHelper.NcOutsetThickness.Top; 36 | } 37 | 38 | public override void ScreenToClient(ref Rectangle screenRect, out Rectangle clientRect) 39 | { 40 | screenRect.Top -= -this.DwmHelper.NcOutsetThickness.Top; 41 | base.ScreenToClient(ref screenRect, out clientRect); 42 | } 43 | 44 | protected override void OnActivate(ref ActivatePacket packet) 45 | { 46 | this.DwmHelper.ApplyDwmConfig(); 47 | base.OnActivate(ref packet); 48 | } 49 | 50 | protected override void OnNcCalcSize(ref NcCalcSizePacket packet) 51 | { 52 | if (this.DwmHelper.TryHandleNcCalcSize(ref packet)) return; 53 | base.OnNcCalcSize(ref packet); 54 | } 55 | 56 | protected override void OnNcHitTest(ref NcHitTestPacket packet) 57 | { 58 | packet.Result = this.DwmHelper.HitTestWithCaptionArea(packet.Point); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /WinApi.Utils/NativePixelBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using WinApi.Core; 4 | 5 | namespace WinApi.Utils 6 | { 7 | public class NativePixelBuffer : IDisposable 8 | { 9 | public IntPtr Handle { get; private set; } 10 | public int BufferLength { get; private set; } 11 | public int Stride { get; private set; } 12 | public int ImageWidth { get; private set; } 13 | public int ImageHeight { get; private set; } 14 | 15 | public void Dispose() 16 | { 17 | GC.SuppressFinalize(this); 18 | if (this.Handle != IntPtr.Zero) 19 | { 20 | Marshal.FreeHGlobal(this.Handle); 21 | this.Handle = IntPtr.Zero; 22 | this.BufferLength = 0; 23 | this.ImageWidth = this.ImageHeight = 0; 24 | } 25 | } 26 | 27 | ~NativePixelBuffer() 28 | { 29 | this.Dispose(); 30 | } 31 | 32 | public bool CheckSize(int imageWidth, int imageHeight) 33 | { 34 | return (imageWidth == this.ImageWidth) && (imageHeight == this.ImageHeight); 35 | } 36 | 37 | public void EnsureSize(int imageWidth, int imageHeight) 38 | { 39 | if (this.CheckSize(imageWidth, imageHeight)) return; 40 | this.Resize(imageWidth, imageHeight); 41 | } 42 | 43 | public void Resize(int imageWidth, int imageHeight) 44 | { 45 | var stride = 4*((imageWidth*32 + 31)/32); 46 | var bufferLength = imageHeight*stride; 47 | if (bufferLength != this.BufferLength) 48 | { 49 | if (this.Handle != IntPtr.Zero) Marshal.FreeHGlobal(this.Handle); 50 | this.Handle = Marshal.AllocHGlobal(bufferLength); 51 | this.BufferLength = bufferLength; 52 | } 53 | 54 | this.Stride = stride; 55 | this.ImageWidth = imageWidth; 56 | this.ImageHeight = imageHeight; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /WinApi.Utils/Types.cs: -------------------------------------------------------------------------------- 1 | namespace WinApi.Utils 2 | { 3 | public struct CartesianValue 4 | { 5 | public int X; 6 | public int Y; 7 | } 8 | } -------------------------------------------------------------------------------- /WinApi.Utils/WinApi.Utils.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard1.4 4 | Prasanna V. Loganathar 5 | Prasanna V. Loganathar 6 | https://www.apache.org/licenses/LICENSE-2.0.txt 7 | https://github.com/prasannavl/WinApi 8 | https://github.com/prasannavl/WinApi 9 | https://raw.githubusercontent.com/prasannavl/WinApi/master/Misc/Logo.png 10 | Copyright © Prasanna V. Loganathar 11 | Utility library that supplements WinApi 12 | 4.0.0 13 | true 14 | win32 native interop 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WinApi.Windows.Controls/Button.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using WinApi.User32; 4 | 5 | namespace WinApi.Windows.Controls 6 | { 7 | public class Button : EventedWindowCore, IConstructionParamsProvider 8 | { 9 | public static Lazy ClassFactory = 10 | new Lazy(() => WindowFactory.CreateForExistingClass("button")); 11 | 12 | protected Button() {} 13 | 14 | IConstructionParams IConstructionParamsProvider.GetConstructionParams() => new ButtonConstructionParams(); 15 | 16 | public static Button Create(string text = null, 17 | WindowStyles? styles = null, 18 | WindowExStyles? exStyles = null, int? x = null, int? y = null, 19 | int? width = null, int? height = null, IntPtr? hParent = null, IntPtr? hMenu = null, 20 | WindowFactory factory = null, ButtonStyles? controlStyles = null) 21 | { 22 | return (factory ?? ClassFactory.Value).CreateWindowEx(() => new Button(), text, styles, exStyles, x, y, 23 | width, 24 | height, hParent, hMenu, (uint) (controlStyles ?? 0)); 25 | } 26 | 27 | public class ButtonConstructionParams : VisibleChildConstructionParams 28 | { 29 | public override int Width => 200; 30 | public override int Height => 35; 31 | public override WindowExStyles ExStyles => 0; 32 | } 33 | 34 | [SuppressMessage("ReSharper", "InconsistentNaming")] 35 | [Flags] 36 | public enum ButtonStyles 37 | { 38 | BS_PUSHBUTTON = 0x00000000, 39 | BS_DEFPUSHBUTTON = 0x00000001, 40 | BS_CHECKBOX = 0x00000002, 41 | BS_AUTOCHECKBOX = 0x00000003, 42 | BS_RADIOBUTTON = 0x00000004, 43 | BS_3STATE = 0x00000005, 44 | BS_AUTO3STATE = 0x00000006, 45 | BS_GROUPBOX = 0x00000007, 46 | BS_USERBUTTON = 0x00000008, 47 | BS_AUTORADIOBUTTON = 0x00000009, 48 | BS_PUSHBOX = 0x0000000A, 49 | BS_OWNERDRAW = 0x0000000B, 50 | BS_TYPEMASK = 0x0000000F, 51 | BS_LEFTTEXT = 0x00000020, 52 | BS_TEXT = 0x00000000, 53 | BS_ICON = 0x00000040, 54 | BS_BITMAP = 0x00000080, 55 | BS_LEFT = 0x00000100, 56 | BS_RIGHT = 0x00000200, 57 | BS_CENTER = 0x00000300, 58 | BS_TOP = 0x00000400, 59 | BS_BOTTOM = 0x00000800, 60 | BS_VCENTER = 0x00000C00, 61 | BS_PUSHLIKE = 0x00001000, 62 | BS_MULTILINE = 0x00002000, 63 | BS_NOTIFY = 0x00004000, 64 | BS_FLAT = 0x00008000, 65 | BS_RIGHTBUTTON = BS_LEFTTEXT 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /WinApi.Windows.Controls/Layouts/HorizontalStretchLayout.cs: -------------------------------------------------------------------------------- 1 | using NetCoreEx.Geometry; 2 | using System.Collections.Generic; 3 | using WinApi.Core; 4 | using WinApi.User32; 5 | 6 | namespace WinApi.Windows.Controls.Layouts 7 | { 8 | public class HorizontalStretchLayout 9 | { 10 | public List Children; 11 | public Rectangle ClientArea; 12 | public Rectangle Margin; 13 | 14 | public HorizontalStretchLayout(int capacity = 0) 15 | { 16 | this.Children = new List(capacity); 17 | } 18 | 19 | public void SetSize(ref Size size) 20 | { 21 | if (this.ClientArea.Size == size) return; 22 | this.ClientArea.Width = size.Width; 23 | this.ClientArea.Height = size.Height; 24 | this.PerformLayout(); 25 | } 26 | 27 | public void PerformLayout() 28 | { 29 | var clientArea = this.ClientArea; 30 | var margin = this.Margin; 31 | var clientRect = clientArea; 32 | Rectangle.Deflate(ref clientRect, ref margin); 33 | var len = this.Children.Count; 34 | 35 | var childSize = clientRect.Size; 36 | childSize.Width = childSize.Width/len; 37 | 38 | var cx = clientRect.Left; 39 | var cy = clientRect.Top; 40 | 41 | foreach (var windowCore in this.Children) 42 | { 43 | windowCore.SetPosition(cx, cy, childSize.Width, childSize.Height); 44 | cx += childSize.Width; 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /WinApi.Windows.Controls/Layouts/HorizontalStretchLayoutWithInnerMargin.cs: -------------------------------------------------------------------------------- 1 | using NetCoreEx.Geometry; 2 | using System.Collections.Generic; 3 | using WinApi.Core; 4 | using WinApi.User32; 5 | 6 | namespace WinApi.Windows.Controls.Layouts 7 | { 8 | public class HorizontalStretchLayoutWithInnerMargin 9 | { 10 | public List Children; 11 | public Rectangle ClientArea; 12 | public Rectangle InnerMargin; 13 | public Rectangle Margin; 14 | 15 | public HorizontalStretchLayoutWithInnerMargin(int capacity = 0) 16 | { 17 | this.Children = new List(capacity); 18 | } 19 | 20 | public void SetSize(ref Size size) 21 | { 22 | if (this.ClientArea.Size == size) return; 23 | this.ClientArea.Width = size.Width; 24 | this.ClientArea.Height = size.Height; 25 | this.PerformLayout(); 26 | } 27 | 28 | public void PerformLayout() 29 | { 30 | var clientArea = this.ClientArea; 31 | var margin = this.Margin; 32 | var innerMargin = this.InnerMargin; 33 | 34 | var clientRect = clientArea; 35 | Rectangle.Deflate(ref clientRect, ref margin); 36 | var len = this.Children.Count; 37 | 38 | var childSize = clientRect.Size; 39 | childSize.Width = childSize.Width/len; 40 | 41 | var cx = clientRect.Left + innerMargin.Left; 42 | var cy = clientRect.Top + innerMargin.Top; 43 | 44 | foreach (var windowCore in this.Children) 45 | { 46 | windowCore.SetPosition(cx, cy, childSize.Width - (innerMargin.Left + innerMargin.Right), 47 | childSize.Height - (innerMargin.Top + innerMargin.Bottom)); 48 | cx += childSize.Width; 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /WinApi.Windows.Controls/StaticBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using WinApi.User32; 4 | 5 | namespace WinApi.Windows.Controls 6 | { 7 | public class StaticBox : EventedWindowCore, IConstructionParamsProvider 8 | { 9 | public static Lazy ClassFactory = 10 | new Lazy(() => WindowFactory.CreateForExistingClass("static")); 11 | 12 | protected StaticBox() {} 13 | 14 | IConstructionParams IConstructionParamsProvider.GetConstructionParams() => new VisibleChildConstructionParams(); 15 | 16 | public static StaticBox Create(string text = null, 17 | WindowStyles? styles = null, 18 | WindowExStyles? exStyles = null, int? x = null, int? y = null, 19 | int? width = null, int? height = null, IntPtr? hParent = null, IntPtr? hMenu = null, 20 | WindowFactory factory = null, StaticStyles? controlStyles = null) 21 | { 22 | return (factory ?? ClassFactory.Value).CreateWindowEx(() => new StaticBox(), text, styles, exStyles, x, y, 23 | width, 24 | height, hParent, hMenu, (uint) (controlStyles ?? 0)); 25 | } 26 | 27 | [SuppressMessage("ReSharper", "InconsistentNaming")] 28 | [Flags] 29 | public enum StaticStyles 30 | { 31 | SS_LEFT = 0x00000000, 32 | SS_CENTER = 0x00000001, 33 | SS_RIGHT = 0x00000002, 34 | SS_ICON = 0x00000003, 35 | SS_BLACKRECT = 0x00000004, 36 | SS_GRAYRECT = 0x00000005, 37 | SS_WHITERECT = 0x00000006, 38 | SS_BLACKFRAME = 0x00000007, 39 | SS_GRAYFRAME = 0x00000008, 40 | SS_WHITEFRAME = 0x00000009, 41 | SS_USERITEM = 0x0000000A, 42 | SS_SIMPLE = 0x0000000B, 43 | SS_LEFTNOWORDWRAP = 0x0000000C, 44 | SS_OWNERDRAW = 0x0000000D, 45 | SS_BITMAP = 0x0000000E, 46 | SS_ENHMETAFILE = 0x0000000F, 47 | SS_ETCHEDHORZ = 0x00000010, 48 | SS_ETCHEDVERT = 0x00000011, 49 | SS_ETCHEDFRAME = 0x00000012, 50 | SS_TYPEMASK = 0x0000001F, 51 | SS_REALSIZECONTROL = 0x00000040, 52 | SS_NOPREFIX = 0x00000080 /* Don't do "&" character translation */, 53 | SS_NOTIFY = 0x00000100, 54 | SS_CENTERIMAGE = 0x00000200, 55 | SS_RIGHTJUST = 0x00000400, 56 | SS_REALSIZEIMAGE = 0x00000800, 57 | SS_SUNKEN = 0x00001000, 58 | SS_EDITCONTROL = 0x00002000, 59 | SS_ENDELLIPSIS = 0x00004000, 60 | SS_PATHELLIPSIS = 0x00008000, 61 | SS_WORDELLIPSIS = 0x0000C000, 62 | SS_ELLIPSISMASK = 0x0000C000 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /WinApi.Windows.Controls/WinApi.Windows.Controls.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard1.4 4 | Prasanna V. Loganathar 5 | Prasanna V. Loganathar 6 | https://www.apache.org/licenses/LICENSE-2.0.txt 7 | https://github.com/prasannavl/WinApi 8 | https://github.com/prasannavl/WinApi 9 | https://raw.githubusercontent.com/prasannavl/WinApi/master/Misc/Logo.png 10 | Copyright © Prasanna V. Loganathar 11 | Win32 Native Controls 12 | 4.0.0 13 | true 14 | win32 native interop 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /WinApi.Windows.Controls/Window.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WinApi.User32; 3 | 4 | namespace WinApi.Windows.Controls 5 | { 6 | public class Window : EventedWindowCore, IConstructionParamsProvider 7 | { 8 | public static Lazy ClassFactory = new Lazy(() => WindowFactory.Create()); 9 | protected Window() {} 10 | 11 | IConstructionParams IConstructionParamsProvider.GetConstructionParams() => new FrameWindowConstructionParams(); 12 | 13 | /// 14 | /// The window creator for standard windows. 15 | /// This is the default methods to create. 16 | /// 17 | public static Window Create(string text = null, 18 | WindowStyles? styles = null, 19 | WindowExStyles? exStyles = null, int? x = null, int? y = null, 20 | int? width = null, int? height = null, IntPtr? hParent = null, IntPtr? hMenu = null, 21 | WindowFactory factory = null) 22 | { 23 | return (factory ?? ClassFactory.Value).CreateWindowEx(() => new Window(), text, styles, exStyles, x, y, 24 | width, 25 | height, hParent, hMenu); 26 | } 27 | 28 | /// 29 | /// The type `Window` is conceptually slightly special, since it forms the base of 30 | /// all fully functional evented windows. So, this is a helper that makes 31 | /// it easy to create any other type of window easily, without the need 32 | /// to create a custom class to provide the protected constructor and 33 | /// IConstructionParamsProvider implementation. 34 | /// This is so that its easy to quickly write other types without having a class for 35 | /// it. But its application's responsibility to make sure that `new` of the Controls 36 | /// aren't called in an attempt to instantiate the window itself, as they'll only 37 | /// create the CLR object and not the actual windows. 38 | /// 39 | public static TWindow Create(string text = null, 40 | WindowStyles? styles = null, 41 | WindowExStyles? exStyles = null, int? x = null, int? y = null, 42 | int? width = null, int? height = null, IntPtr? hParent = null, IntPtr? hMenu = null, 43 | WindowFactory factory = null, uint? controlStyles = null) 44 | where TWindow : WindowCore, IConstructionParamsProvider, new() 45 | { 46 | return (factory ?? ClassFactory.Value).CreateWindowEx(() => new TWindow(), text, styles, exStyles, x, y, 47 | width, height, hParent, 48 | hMenu, controlStyles); 49 | } 50 | 51 | /// 52 | /// Another helper for `Window` class, since its conceptually slightly special. 53 | /// This allows any TWindow type to be created, whether or not they implement the 54 | /// IConstructionParamsProvider to help with construction. This is purely a helper 55 | /// to facilitate such a scenario. 56 | /// 57 | public static TWindow CreateWith(IConstructionParams constructionParams = null, string text = null, 58 | WindowStyles? styles = null, 59 | WindowExStyles? exStyles = null, int? x = null, int? y = null, 60 | int? width = null, int? height = null, IntPtr? hParent = null, IntPtr? hMenu = null, 61 | WindowFactory factory = null, uint? controlStyles = null) 62 | where TWindow : WindowCore, new() 63 | { 64 | return (factory ?? ClassFactory.Value).CreateWindow(() => new TWindow(), 65 | text, styles, exStyles, x, y, 66 | width, height, hParent, 67 | hMenu, controlStyles, constructionParams); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /WinApi/Core/Types.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // ReSharper disable InconsistentNaming 4 | 5 | namespace WinApi.Core 6 | { 7 | public enum HResult : uint 8 | { 9 | /// 10 | /// Operation successful 11 | /// 12 | S_OK = 0x00000000, 13 | 14 | /// 15 | /// Not implemented 16 | /// 17 | E_NOTIMPL = 0x80004001, 18 | 19 | /// 20 | /// No such interface supported 21 | /// 22 | E_NOINTERFACE = 0x80004002, 23 | 24 | /// 25 | /// Pointer that is not valid 26 | /// 27 | E_POINTER = 0x80004003, 28 | 29 | /// 30 | /// Operation aborted 31 | /// 32 | E_ABORT = 0x80004004, 33 | 34 | /// 35 | /// Unspecified failure 36 | /// 37 | E_FAIL = 0x80004005, 38 | 39 | /// 40 | /// Unexpected failure 41 | /// 42 | E_UNEXPECTED = 0x8000FFFF, 43 | 44 | /// 45 | /// General access denied error 46 | /// 47 | E_ACCESSDENIED = 0x80070005, 48 | 49 | /// 50 | /// Handle that is not valid 51 | /// 52 | E_HANDLE = 0x80070006, 53 | 54 | /// 55 | /// Failed to allocate necessary memory 56 | /// 57 | E_OUTOFMEMORY = 0x8007000E, 58 | 59 | /// 60 | /// One or more arguments are not valid 61 | /// 62 | E_INVALIDARG = 0x80070057 63 | } 64 | } -------------------------------------------------------------------------------- /WinApi/DwmApi/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NetCoreEx.Geometry; 8 | using WinApi.Core; 9 | 10 | // ReSharper disable InconsistentNaming 11 | 12 | namespace WinApi.DwmApi 13 | { 14 | public static class DwmApiHelpers 15 | { 16 | public static unsafe HResult DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttributeType dwAttribute, 17 | [In] ref int attrValue) 18 | { 19 | fixed (int* ptr = &attrValue) return DwmApiMethods.DwmSetWindowAttribute(hwnd, dwAttribute, new IntPtr(ptr), sizeof(int)); 20 | } 21 | 22 | public static unsafe HResult DwmGetWindowAttribute(IntPtr hwnd, DwmWindowAttributeType dwAttribute, 23 | out Rectangle rect) 24 | { 25 | fixed (Rectangle* ptr = &rect) return DwmApiMethods.DwmGetWindowAttribute(hwnd, dwAttribute, new IntPtr(ptr), (uint) sizeof(Rectangle)); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /WinApi/DwmApi/Methods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using NetCoreEx.Geometry; 4 | using WinApi.Core; 5 | using WinApi.UxTheme; 6 | 7 | namespace WinApi.DwmApi 8 | { 9 | public static class DwmApiMethods 10 | { 11 | public const string LibraryName = "dwmapi"; 12 | 13 | [DllImport(LibraryName, ExactSpelling = true)] 14 | public static extern HResult DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttributeType dwAttribute, 15 | IntPtr pvAttribute, 16 | uint attrSize); 17 | 18 | [DllImport(LibraryName, ExactSpelling = true)] 19 | public static extern HResult DwmGetWindowAttribute(IntPtr hwnd, DwmWindowAttributeType dwAttribute, 20 | IntPtr pvAttribute, 21 | uint cbAttribute); 22 | 23 | [DllImport(LibraryName, ExactSpelling = true)] 24 | public static extern HResult DwmIsCompositionEnabled(out bool pfEnabled); 25 | 26 | [DllImport(LibraryName, ExactSpelling = true)] 27 | public static extern HResult DwmExtendFrameIntoClientArea(IntPtr hwnd, [In] ref Margins margins); 28 | 29 | [DllImport(LibraryName, ExactSpelling = true)] 30 | public static extern bool DwmDefWindowProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, 31 | out IntPtr lResult); 32 | 33 | [DllImport(LibraryName, ExactSpelling = true)] 34 | public static extern HResult DwmGetColorizationColor(out int pcrColorization, out bool pfOpaqueBlend); 35 | } 36 | } -------------------------------------------------------------------------------- /WinApi/Gdi32/CustomTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WinApi.Gdi32 9 | { 10 | public class NativeBitmapInfoHandle : CriticalHandle 11 | { 12 | public unsafe NativeBitmapInfoHandle(ref BitmapInfo bitmapInfo) : base(new IntPtr(0)) 13 | { 14 | var quads = bitmapInfo.Colors; 15 | var quadsLength = quads.Length; 16 | if (quadsLength == 0) { quadsLength = 1; } 17 | var success = false; 18 | var ptr = IntPtr.Zero; 19 | try 20 | { 21 | ptr = 22 | Marshal.AllocHGlobal(Marshal.SizeOf() + Marshal.SizeOf()*quadsLength); 23 | var headerPtr = (BitmapInfoHeader*) ptr.ToPointer(); 24 | *headerPtr = bitmapInfo.Header; 25 | var quadPtr = (RgbQuad*) (headerPtr + 1); 26 | var i = 0; 27 | for (; i < quads.Length; i++) { *(quadPtr + i) = quads[i]; } 28 | if (i == 0) { *quadPtr = new RgbQuad(); } 29 | this.SetHandle(ptr); 30 | success = true; 31 | } 32 | finally 33 | { 34 | if (!success) 35 | { 36 | this.SetHandleAsInvalid(); 37 | Marshal.FreeHGlobal(ptr); 38 | } 39 | } 40 | } 41 | 42 | public override bool IsInvalid => this.handle == IntPtr.Zero; 43 | 44 | protected override bool ReleaseHandle() 45 | { 46 | Marshal.FreeHGlobal(this.handle); 47 | return true; 48 | } 49 | 50 | public IntPtr GetDangerousHandle() => this.handle; 51 | } 52 | } -------------------------------------------------------------------------------- /WinApi/Gdi32/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Runtime.InteropServices.ComTypes; 4 | using System.Threading; 5 | 6 | // ReSharper disable InconsistentNaming 7 | 8 | namespace WinApi.Gdi32 9 | { 10 | public static class Gdi32Helpers 11 | { 12 | public static IntPtr GetStockObject(StockObject fnObject) 13 | { 14 | return Gdi32Methods.GetStockObject((int) fnObject); 15 | } 16 | 17 | public static IntPtr CreateDIBSection(IntPtr hdc, ref BitmapInfo bitmapInfo, 18 | DibBmiColorUsageFlag iUsage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset) 19 | { 20 | using (var pbmi = BitmapInfo.NativeAlloc(ref bitmapInfo)) 21 | { 22 | return Gdi32Methods.CreateDIBSection(hdc, pbmi.GetDangerousHandle(), iUsage, out ppvBits, hSection, 23 | dwOffset); 24 | } 25 | } 26 | 27 | public static unsafe IntPtr CreateDIBSection(IntPtr hdc, ref BitmapInfoHeader bitmapInfoHeader, 28 | DibBmiColorUsageFlag iUsage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset) 29 | { 30 | fixed (BitmapInfoHeader* bitmapInfoHeaderPtr = &bitmapInfoHeader) 31 | { 32 | return Gdi32Methods.CreateDIBSection(hdc, new IntPtr(bitmapInfoHeaderPtr), iUsage, out ppvBits, hSection, 33 | dwOffset); 34 | } 35 | } 36 | 37 | public static IntPtr CreateDIBitmap(IntPtr hdc, ref BitmapInfoHeader 38 | lpbmih, uint fdwInit, byte[] lpbInit, ref BitmapInfo bitmapInfo, 39 | DibBmiColorUsageFlag fuUsage) 40 | { 41 | using (var pbmi = BitmapInfo.NativeAlloc(ref bitmapInfo)) 42 | { 43 | return Gdi32Methods.CreateDIBitmap(hdc, ref lpbmih, fdwInit, lpbInit, pbmi.GetDangerousHandle(), 44 | fuUsage); 45 | } 46 | } 47 | 48 | public static int SetDIBitsToDevice(IntPtr hdc, int xDest, int yDest, uint 49 | dwWidth, uint dwHeight, int xSrc, int ySrc, uint uStartScan, uint cScanLines, 50 | byte[] lpvBits, ref BitmapInfo bitmapInfo, DibBmiColorUsageFlag fuColorUse) 51 | { 52 | using (var pbmi = BitmapInfo.NativeAlloc(ref bitmapInfo)) 53 | { 54 | return Gdi32Methods.SetDIBitsToDevice(hdc, xDest, yDest, 55 | dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, pbmi.GetDangerousHandle(), 56 | fuColorUse); 57 | } 58 | } 59 | 60 | public static unsafe int SetDIBitsToDevice(IntPtr hdc, int xDest, int yDest, uint 61 | dwWidth, uint dwHeight, int xSrc, int ySrc, uint uStartScan, uint cScanLines, 62 | byte[] lpvBits, ref BitmapInfoHeader bitmapInfoHeader, DibBmiColorUsageFlag fuColorUse) 63 | { 64 | fixed (BitmapInfoHeader* bitmapInfoHeaderPtr = &bitmapInfoHeader) 65 | { 66 | return Gdi32Methods.SetDIBitsToDevice(hdc, xDest, yDest, 67 | dwWidth, dwHeight, xSrc, ySrc, uStartScan, cScanLines, lpvBits, new IntPtr(bitmapInfoHeaderPtr), 68 | fuColorUse); 69 | } 70 | } 71 | 72 | public static unsafe int SetRgbBitsToDevice(IntPtr hdc, int width, int height, byte[] bits, int xSrc = 0, 73 | int ySrc = 0, int xDest = 0, int yDest = 0, bool isRgba = true, bool isImageTopDown = true) 74 | { 75 | fixed (byte* ptr = &bits[0]) { 76 | return SetRgbBitsToDevice(hdc, width, height, (IntPtr) ptr, xSrc, ySrc, xDest, yDest, isRgba); 77 | } 78 | } 79 | 80 | public static unsafe int SetRgbBitsToDevice(IntPtr hdc, int width, int height, IntPtr pixelBufferPtr, 81 | int xSrc = 0, 82 | int ySrc = 0, int xDest = 0, int yDest = 0, bool isRgba = true, bool isImageTopDown = true) 83 | { 84 | var bi = new BitmapInfoHeader 85 | { 86 | Size = (uint) Marshal.SizeOf(), 87 | Width = width, 88 | Height = isImageTopDown ? -height : height, 89 | CompressionMode = BitmapCompressionMode.BI_RGB, 90 | BitCount = isRgba ? (ushort) 32 : (ushort) 24, 91 | Planes = 1 92 | }; 93 | return Gdi32Methods.SetDIBitsToDevice(hdc, xDest, yDest, (uint) width, (uint) height, xSrc, ySrc, 0, 94 | (uint) height, pixelBufferPtr, new IntPtr(&bi), 95 | DibBmiColorUsageFlag.DIB_RGB_COLORS); 96 | } 97 | 98 | public static IntPtr CreateSolidBrush(uint r, uint g, uint b) 99 | { 100 | return Gdi32Methods.CreateSolidBrush(Bgr32(r, g, b)); 101 | } 102 | 103 | public static uint Bgr32(uint r, uint g, uint b) 104 | { 105 | return r | (g << 8) | (b << 16); 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /WinApi/Kernel32/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NetCoreEx.BinaryExtensions; 8 | 9 | // ReSharper disable InconsistentNaming 10 | 11 | namespace WinApi.Kernel32 12 | { 13 | public static class Kernel32Helpers 14 | { 15 | public static Version GetVersion() 16 | { 17 | var dwVersion = Kernel32Methods.GetVersion(); 18 | var build = dwVersion < 0x80000000 ? dwVersion.HighAsUInt() : 0; // (DWORD) (HIWORD(dwVersion)) 19 | var v = new Version( 20 | (byte) dwVersion.Low(), // (DWORD)(LOBYTE(LOWORD(dwVersion))) 21 | (dwVersion.Low() >> 8) & 0xff, 22 | (int) build // (DWORD)(HIBYTE(LOWORD(dwVersion))) 23 | ); 24 | return v; 25 | } 26 | 27 | public static bool IsWin8OrGreater(Version version = null) 28 | { 29 | if (version == null) version = GetVersion(); 30 | if (version.Major > 5) 31 | { 32 | if ((version.Major > 6) || (version.Minor > 1)) return true; 33 | } 34 | return false; 35 | } 36 | 37 | public static bool IsWin8Point1OrGreater(Version version = null) 38 | { 39 | if (version == null) version = GetVersion(); 40 | if (version.Major > 5) 41 | { 42 | if ((version.Major > 6) || (version.Minor > 2)) return true; 43 | } 44 | return false; 45 | } 46 | 47 | public static bool IsWin10OrGreater(Version version = null) 48 | { 49 | if (version == null) version = GetVersion(); 50 | return version.Major > 6; 51 | } 52 | 53 | public static bool GetIsProcessorAMD64() 54 | { 55 | SystemInfo info; 56 | Kernel32Methods.GetNativeSystemInfo(out info); 57 | return info.ProcessorArchitecture == (uint) ProcessArchitecture.PROCESSOR_ARCHITECTURE_AMD64; 58 | } 59 | 60 | public static class ProcessUserModeExceptionFilter 61 | { 62 | const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1; 63 | 64 | [DllImport(Kernel32Methods.LibraryName)] 65 | public static extern bool SetProcessUserModeExceptionPolicy(uint dwFlags); 66 | 67 | [DllImport(Kernel32Methods.LibraryName)] 68 | public static extern bool GetProcessUserModeExceptionPolicy(out uint dwFlags); 69 | 70 | private static bool IsApiAvailable() 71 | { 72 | if (GetIsProcessorAMD64()) 73 | { 74 | var ver = GetVersion(); 75 | return (ver.Major == 6) && (ver.Minor == 1) && (ver.Build >= 7601); 76 | } 77 | return false; 78 | } 79 | 80 | public static bool Disable() 81 | { 82 | if (IsApiAvailable()) 83 | { 84 | uint dwFlags; 85 | if (GetProcessUserModeExceptionPolicy(out dwFlags)) 86 | { 87 | // Turn off the bit 88 | dwFlags &= ~PROCESS_CALLBACK_FILTER_ENABLED; 89 | return SetProcessUserModeExceptionPolicy(dwFlags); 90 | } 91 | } 92 | return false; 93 | } 94 | 95 | public static bool Enable() 96 | { 97 | if (IsApiAvailable()) 98 | { 99 | uint dwFlags; 100 | if (GetProcessUserModeExceptionPolicy(out dwFlags)) 101 | { 102 | // Turn off the bit 103 | dwFlags |= PROCESS_CALLBACK_FILTER_ENABLED; 104 | return SetProcessUserModeExceptionPolicy(dwFlags); 105 | } 106 | } 107 | return false; 108 | } 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /WinApi/Kernel32/Types.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WinApi.Kernel32 9 | { 10 | [StructLayout(LayoutKind.Sequential)] 11 | public struct SystemInfo 12 | { 13 | public ushort ProcessorArchitecture; 14 | ushort Reserved; 15 | public uint PageSize; 16 | public IntPtr MinimumApplicationAddress; 17 | public IntPtr MaximumApplicationAddress; 18 | public IntPtr ActiveProcessorMask; 19 | public uint NumberOfProcessors; 20 | public uint ProcessorType; 21 | public uint AllocationGranularity; 22 | public ushort ProcessorLevel; 23 | public ushort ProcessorRevision; 24 | public uint OemId => ((uint) this.ProcessorArchitecture << 8) | this.Reserved; 25 | } 26 | 27 | [StructLayout(LayoutKind.Sequential)] 28 | public struct SecurityAttributes 29 | { 30 | public uint Length; 31 | public IntPtr SecurityDescriptor; 32 | public uint IsHandleInheritedValue; 33 | 34 | public bool IsHandleInherited => this.IsHandleInheritedValue > 0; 35 | } 36 | 37 | [StructLayout(LayoutKind.Sequential)] 38 | public struct FileTime 39 | { 40 | public uint Low; 41 | public uint High; 42 | 43 | public ulong Value => ((ulong) this.High << 32) | this.Low; 44 | } 45 | 46 | [StructLayout(LayoutKind.Sequential)] 47 | public struct SystemTime 48 | { 49 | public ushort Year; 50 | public ushort Month; 51 | public ushort DayOfWeek; 52 | public ushort Day; 53 | public ushort Hour; 54 | public ushort Minute; 55 | public ushort Second; 56 | public ushort Milliseconds; 57 | } 58 | 59 | [StructLayout(LayoutKind.Sequential)] 60 | public struct FileAttributeData 61 | { 62 | public FileAttributes Attributes; 63 | public FileTime CreationTime; 64 | public FileTime LastAccessTime; 65 | public FileTime LastWriteTime; 66 | 67 | public uint FileSizeHigh; 68 | public uint FileSizeLow; 69 | 70 | public ulong FileSize => ((ulong) this.FileSizeHigh << 32) | this.FileSizeLow; 71 | } 72 | } -------------------------------------------------------------------------------- /WinApi/KernelBase/Methods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WinApi.KernelBase 9 | { 10 | public static class Kernel32Methods 11 | { 12 | public const string LibraryName = "kernelbase"; 13 | 14 | [DllImport(LibraryName, ExactSpelling = true)] 15 | public static extern bool CompareObjectHandles(IntPtr hFirstObjectHandle, IntPtr hSecondObjectHandle); 16 | } 17 | } -------------------------------------------------------------------------------- /WinApi/Properties.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace WinApi 9 | { 10 | internal static class Properties 11 | { 12 | #if !ANSI 13 | public const CharSet BuildCharSet = CharSet.Unicode; 14 | #else 15 | public const CharSet BuildCharSet = CharSet.Ansi; 16 | #endif 17 | } 18 | } -------------------------------------------------------------------------------- /WinApi/ShCore/Methods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using WinApi.Core; 4 | 5 | namespace WinApi.ShCore 6 | { 7 | public static class ShCoreMethods 8 | { 9 | public const string LibraryName = "shcore"; 10 | 11 | [DllImport(LibraryName, ExactSpelling = true)] 12 | public static extern HResult GetDpiForMonitor(IntPtr hmonitor, MonitorDpiType dpiType, out uint dpiX, 13 | out uint dpiY); 14 | } 15 | } -------------------------------------------------------------------------------- /WinApi/ShCore/Types.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable InconsistentNaming 2 | 3 | namespace WinApi.ShCore 4 | { 5 | public enum MonitorDpiType 6 | { 7 | /// 8 | /// The effective DPI. This value should be used when determining the correct scale factor for scaling UI elements. 9 | /// This incorporates the scale factor set by the user for this specific display. 10 | /// 11 | MDT_EFFECTIVE_DPI = 0, 12 | 13 | /// 14 | /// The angular DPI. This DPI ensures rendering at a compliant angular resolution on the screen. This does not include 15 | /// the scale factor set by the user for this specific display. 16 | /// 17 | MDT_ANGULAR_DPI = 1, 18 | 19 | /// 20 | /// The raw DPI. This value is the linear DPI of the screen as measured on the screen itself. Use this value when you 21 | /// want to read the pixel density and not the recommended scaling setting. This does not include the scale factor set 22 | /// by the user for this specific display and is not guaranteed to be a supported DPI value. 23 | /// 24 | MDT_RAW_DPI = 2, 25 | MDT_DEFAULT = MDT_EFFECTIVE_DPI 26 | } 27 | } -------------------------------------------------------------------------------- /WinApi/User32/Experimental/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace WinApi.User32.Experimental 5 | { 6 | public static class User32ExperimentalHelpers 7 | { 8 | public static void EnableBlurBehind(IntPtr hwnd) 9 | { 10 | var accent = new AccentPolicy(); 11 | var accentStructSize = Marshal.SizeOf(); 12 | accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; 13 | var accentPtr = Marshal.AllocHGlobal(accentStructSize); 14 | try 15 | { 16 | Marshal.StructureToPtr(accent, accentPtr, false); 17 | var data = new WindowCompositionAttributeData 18 | { 19 | Attribute = WindowCompositionAttributeType.WCA_ACCENT_POLICY, 20 | DataSize = accentStructSize, 21 | Data = accentPtr 22 | }; 23 | User32ExperimentalMethods.SetWindowCompositionAttribute(hwnd, ref data); 24 | } 25 | finally { Marshal.FreeHGlobal(accentPtr); } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /WinApi/User32/Experimental/Methods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace WinApi.User32.Experimental 5 | { 6 | public static class User32ExperimentalMethods 7 | { 8 | [DllImport(User32Methods.LibraryName, CharSet = Properties.BuildCharSet)] 9 | internal static extern bool SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); 10 | } 11 | } -------------------------------------------------------------------------------- /WinApi/User32/Experimental/Types.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | // ReSharper disable InconsistentNaming 5 | 6 | namespace WinApi.User32.Experimental 7 | { 8 | 9 | #region Constants 10 | 11 | public enum WindowCompositionAttributeType 12 | { 13 | WCA_ACCENT_POLICY = 19 14 | } 15 | 16 | public enum AccentState 17 | { 18 | ACCENT_DISABLED = 0, 19 | ACCENT_ENABLE_GRADIENT = 1, 20 | ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, 21 | ACCENT_ENABLE_BLURBEHIND = 3, 22 | ACCENT_INVALID_STATE = 4 23 | } 24 | 25 | [Flags] 26 | public enum AccentFlags 27 | { 28 | AF_LEFTBORDER = 0x20, 29 | AF_TOPBORDER = 0x40, 30 | AF_RIGHTBORDER = 0x80, 31 | AF_BOTTOMBORDER = 0x100, 32 | AF_ALLBORDERS = AF_LEFTBORDER | AF_TOPBORDER | AF_RIGHTBORDER | AF_BOTTOMBORDER 33 | } 34 | 35 | #endregion 36 | 37 | [StructLayout(LayoutKind.Sequential)] 38 | public struct WindowCompositionAttributeData 39 | { 40 | public WindowCompositionAttributeType Attribute; 41 | public IntPtr Data; 42 | public int DataSize; 43 | } 44 | 45 | [StructLayout(LayoutKind.Sequential)] 46 | public struct AccentPolicy 47 | { 48 | public AccentState AccentState; 49 | public AccentFlags AccentFlags; 50 | public int GradientColor; 51 | public int AnimationId; 52 | } 53 | } -------------------------------------------------------------------------------- /WinApi/UxTheme/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using WinApi.Core; 8 | 9 | namespace WinApi.UxTheme 10 | { 11 | public static class UxThemeHelpers 12 | { 13 | public static unsafe HResult SetWindowThemeNonClientAttributes(IntPtr hwnd, 14 | WindowThemeNcAttributeFlags mask, 15 | WindowThemeNcAttributeFlags attributes) 16 | { 17 | var opts = new WindowThemeAttributeOptions 18 | { 19 | Mask = (uint) mask, 20 | Flags = (uint) attributes 21 | }; 22 | return UxThemeMethods.SetWindowThemeAttribute(hwnd, WindowThemeAttributeType.WTA_NONCLIENT, 23 | new IntPtr(&opts), (uint) Marshal.SizeOf()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /WinApi/WinApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard1.4 5 | Prasanna V. Loganathar 6 | Prasanna V. Loganathar 7 | https://www.apache.org/licenses/LICENSE-2.0.txt 8 | https://github.com/prasannavl/WinApi 9 | https://github.com/prasannavl/WinApi 10 | https://raw.githubusercontent.com/prasannavl/WinApi/master/Misc/Logo.png 11 | Copyright © Prasanna V. Loganathar 12 | A simple, direct, ultra-thin CLR library for high-performance Win32 Native Interop 13 | 4.0.0 14 | true 15 | win32 native interop 16 | 17 | 18 | 19 | true 20 | TRACE;RELEASE;NETSTANDARD1_4 21 | 22 | 23 | 24 | true 25 | TRACE;DEBUG;NETSTANDARD1_4 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /WinApi/Windows/ConstructionParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WinApi.User32; 3 | 4 | namespace WinApi.Windows 5 | { 6 | public interface IConstructionParamsProvider 7 | { 8 | IConstructionParams GetConstructionParams(); 9 | } 10 | 11 | public interface IConstructionParams 12 | { 13 | WindowStyles Styles { get; } 14 | WindowExStyles ExStyles { get; } 15 | uint ControlStyles { get; } 16 | int Width { get; } 17 | int Height { get; } 18 | int X { get; } 19 | int Y { get; } 20 | IntPtr ParentHandle { get; } 21 | IntPtr MenuHandle { get; } 22 | } 23 | 24 | public class ConstructionParams : IConstructionParams 25 | { 26 | public virtual int X => (int) CreateWindowFlags.CW_USEDEFAULT; 27 | public virtual int Y => (int) CreateWindowFlags.CW_USEDEFAULT; 28 | public virtual int Width => (int) CreateWindowFlags.CW_USEDEFAULT; 29 | public virtual int Height => (int) CreateWindowFlags.CW_USEDEFAULT; 30 | public virtual IntPtr ParentHandle => IntPtr.Zero; 31 | public virtual IntPtr MenuHandle => IntPtr.Zero; 32 | public virtual WindowStyles Styles => 0; 33 | public virtual uint ControlStyles => 0; 34 | public virtual WindowExStyles ExStyles => 0; 35 | } 36 | 37 | public class FrameWindowConstructionParams : ConstructionParams 38 | { 39 | public override WindowStyles Styles 40 | => WindowStyles.WS_OVERLAPPEDWINDOW | WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPSIBLINGS; 41 | 42 | public override WindowExStyles ExStyles 43 | => WindowExStyles.WS_EX_APPWINDOW | WindowExStyles.WS_EX_WINDOWEDGE; 44 | } 45 | 46 | public class VisibleChildConstructionParams : ConstructionParams 47 | { 48 | public override WindowStyles Styles 49 | => WindowStyles.WS_VISIBLE | WindowStyles.WS_CHILD; 50 | 51 | public override WindowExStyles ExStyles 52 | => WindowExStyles.WS_EX_STATICEDGE; 53 | } 54 | } -------------------------------------------------------------------------------- /WinApi/Windows/EventLoop.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WinApi.User32; 3 | using WinApi.Windows.Helpers; 4 | 5 | namespace WinApi.Windows 6 | { 7 | public interface IEventLoop 8 | { 9 | int Run(WindowCore mainWindow = null); 10 | } 11 | 12 | public abstract class EventLoopCore : IEventLoop 13 | { 14 | protected object State; 15 | 16 | protected EventLoopCore(object state) 17 | { 18 | this.State = state; 19 | } 20 | 21 | public int Run(WindowCore mainWindow = null) 22 | { 23 | Action destroyHandler = () => { MessageHelpers.PostQuitMessage(); }; 24 | if (mainWindow != null) mainWindow.Destroyed += destroyHandler; 25 | var res = this.RunCore(); 26 | // Technically, this can be avoided by setting the handler to auto disconnect. 27 | // However, this helps keep the mainWindow alive, and use this instead of 28 | // GC.KeepAlive pattern. 29 | if (mainWindow != null) mainWindow.Destroyed -= destroyHandler; 30 | return res; 31 | } 32 | 33 | public abstract int RunCore(); 34 | } 35 | 36 | 37 | public class EventLoop : EventLoopCore 38 | { 39 | public EventLoop(object state = null) : base(state) {} 40 | 41 | public override int RunCore() 42 | { 43 | Message msg; 44 | int res; 45 | while ((res = User32Methods.GetMessage(out msg, IntPtr.Zero, 0, 0)) > 0) 46 | { 47 | User32Methods.TranslateMessage(ref msg); 48 | User32Methods.DispatchMessage(ref msg); 49 | } 50 | return res; 51 | } 52 | } 53 | 54 | public class RealtimeEventLoop : EventLoopCore 55 | { 56 | public RealtimeEventLoop(object state = null) : base(state) {} 57 | 58 | public override int RunCore() 59 | { 60 | Message msg; 61 | var quitMsgId = (uint) WM.QUIT; 62 | do 63 | { 64 | if (User32Helpers.PeekMessage(out msg, IntPtr.Zero, 0, 0, PeekMessageFlags.PM_REMOVE)) 65 | { 66 | User32Methods.TranslateMessage(ref msg); 67 | User32Methods.DispatchMessage(ref msg); 68 | } 69 | } while (msg.Value != quitMsgId); 70 | return 0; 71 | } 72 | } 73 | 74 | public abstract class InterceptableEventLoopCore : EventLoopCore 75 | { 76 | protected InterceptableEventLoopCore(object state) : base(state) {} 77 | protected virtual bool Preprocess(ref Message msg) => true; 78 | protected virtual bool PostTranslate(ref Message msg) => true; 79 | protected virtual void PostProcess(ref Message msg) {} 80 | } 81 | 82 | public abstract class InterceptableEventLoopBase : InterceptableEventLoopCore 83 | { 84 | protected InterceptableEventLoopBase(object state) : base(state) {} 85 | 86 | public override int RunCore() 87 | { 88 | Message msg; 89 | int res; 90 | while ((res = User32Methods.GetMessage(out msg, IntPtr.Zero, 0, 0)) > 0) 91 | { 92 | if (this.Preprocess(ref msg)) 93 | { 94 | User32Methods.TranslateMessage(ref msg); 95 | if (this.PostTranslate(ref msg)) User32Methods.DispatchMessage(ref msg); 96 | this.PostProcess(ref msg); 97 | } 98 | } 99 | return res; 100 | } 101 | } 102 | 103 | public abstract class InterceptableRealtimeEventLoopBase : InterceptableEventLoopCore 104 | { 105 | protected InterceptableRealtimeEventLoopBase(object state) : base(state) {} 106 | 107 | public override int RunCore() 108 | { 109 | Message msg; 110 | var quitMsg = (uint) WM.QUIT; 111 | do 112 | { 113 | if (User32Helpers.PeekMessage(out msg, IntPtr.Zero, 0, 0, PeekMessageFlags.PM_REMOVE)) 114 | if (this.Preprocess(ref msg)) 115 | { 116 | User32Methods.TranslateMessage(ref msg); 117 | if (this.PostTranslate(ref msg)) User32Methods.DispatchMessage(ref msg); 118 | this.PostProcess(ref msg); 119 | } 120 | } while (msg.Value != quitMsg); 121 | return 0; 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /WinApi/Windows/Helpers/MessageBoxHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WinApi.User32; 3 | 4 | namespace WinApi.Windows.Helpers 5 | { 6 | public class MessageBoxHelpers 7 | { 8 | public static MessageBoxResult ShowError(object errorObject, string infoMessage = null, string title = null, 9 | IntPtr parentHwnd = default(IntPtr), 10 | MessageBoxFlags flags = 11 | MessageBoxFlags.MB_OK | MessageBoxFlags.MB_ICONERROR | MessageBoxFlags.MB_SYSTEMMODAL) 12 | { 13 | const string defaultTitle = "Error"; 14 | const string defaultInfoMessage = "Oh snap! Something went wrong."; 15 | 16 | title = title ?? defaultTitle; 17 | var ex = errorObject as Exception; 18 | if (ex == null) 19 | { 20 | return User32Helpers.MessageBox(parentHwnd, 21 | infoMessage ?? defaultInfoMessage + 22 | $"\n\n{errorObject?.ToString() ?? "No additional information available."}", 23 | title, flags); 24 | } 25 | var exMessage = ex.Message ?? "No information message available."; 26 | string msg; 27 | if (infoMessage != null) { msg = infoMessage + "\n\n" + exMessage; } 28 | else 29 | { msg = defaultInfoMessage + "\n\n" + exMessage; } 30 | return User32Helpers.MessageBox(parentHwnd, 31 | $"{msg}" + 32 | $"\n\nStackTrace:\n\n{ex.StackTrace}", 33 | title, flags); 34 | } 35 | 36 | public static MessageBoxResult Show(string message, string title = null, 37 | IntPtr parentHwnd = default(IntPtr), 38 | MessageBoxFlags flags = 39 | MessageBoxFlags.MB_OK | MessageBoxFlags.MB_ICONINFORMATION) 40 | { 41 | const string defaultTitle = "Information"; 42 | title = title ?? defaultTitle; 43 | return User32Helpers.MessageBox(parentHwnd, 44 | message, title, flags); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /WinApi/Windows/Helpers/MessageHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WinApi.DwmApi; 3 | using WinApi.User32; 4 | 5 | namespace WinApi.Windows.Helpers 6 | { 7 | public static class MessageHelpers 8 | { 9 | public static bool RunDwmDefWindowProc(ref WindowMessage msg) 10 | { 11 | return DwmApiMethods.DwmDefWindowProc(msg.Hwnd, (uint) msg.Id, msg.WParam, msg.LParam, out msg.Result); 12 | } 13 | 14 | public static void PostQuitMessage(int exitCode = 0) 15 | { 16 | User32Methods.PostQuitMessage(exitCode); 17 | } 18 | 19 | public static void RunWindowProc(WindowCore coreWindow, ref WindowMessage msg) 20 | { 21 | msg.SetResult(coreWindow.WindowProc(msg.Hwnd, (uint) msg.Id, msg.WParam, msg.LParam)); 22 | } 23 | } 24 | } --------------------------------------------------------------------------------