Compare commits

...

109 Commits
v1.0 ... master

Author SHA1 Message Date
JFronny
baffd311ce Make DB info public 2020-11-19 19:55:41 +01:00
JFronny
5b5e359efb Because of CI there cant be net5. sad. 2020-11-19 19:43:47 +01:00
JFronny
cae077a5cf netstandard2.1 because the world apparently isn't ready yet 2020-11-19 19:37:33 +01:00
JFronny
d80c1ac5a0 Add AspNet GenericExtensions 2020-11-19 19:35:17 +01:00
JFronny
9d87c47f1c AspNet extensions 2020-11-19 19:26:36 +01:00
JFronny
bb5ea72041 .NET Standard 2.1 & .NET 5.0 2020-11-11 16:37:40 +01:00
J. Fronny
454d902f04 Merge branch 'renovate/system.management-5.x' into 'master'
Update dependency System.Management to v5

See merge request JFronny/CC-Functions!2
2020-11-10 15:21:36 +00:00
Renovate Bot
fc68a0f6f7
Update dependency System.Management to v5 2020-11-10 12:17:13 +00:00
J. Fronny
dba8d63af5 Merge branch 'renovate/system.security.cryptography.protecteddata-5.x' into 'master'
Update dependency System.Security.Cryptography.ProtectedData to v5

See merge request JFronny/CC-Functions!3
2020-11-10 12:01:40 +00:00
Renovate Bot
65ae6b84e7
Update dependency System.Security.Cryptography.ProtectedData to v5 2020-11-10 01:18:08 +00:00
JFronny
1e451b78f9 Add initial argument parsing capabilites to CC_Functions.CommandLine 2020-09-11 11:41:08 +02:00
JFronny
7c9a5aa73d Include CC_Functions.Core in README and nugets artifact 2020-09-11 10:46:29 +02:00
JFronny
85a67cd64a [Attempt] introduce CC_Functions.Core 2020-09-11 10:38:55 +02:00
J. Fronny
0fa5fd6e82 Update .gitlab-ci.yml 2020-08-31 19:14:46 +00:00
J. Fronny
ea2572d585 Update .gitlab-ci.yml 2020-08-31 19:01:19 +00:00
J. Fronny
0743b09941 Update .gitlab-ci.yml 2020-07-31 13:36:39 +00:00
J. Fronny
45b7c9263c Add LICENSE 2020-06-27 16:23:37 +00:00
J. Fronny
94bd0fa189 Merge branch 'renovate/configure' into 'master'
Configure Renovate

See merge request JFronny/CC-Functions!1
2020-06-23 12:09:01 +00:00
Renovate Bot
3fc3cd61b5
Add renovate.json 2020-06-23 08:48:43 +00:00
J. Fronny
282a249f3f Update README.md 2020-06-18 20:02:24 +00:00
J. Fronny
a24905c884 Update README.md 2020-06-18 20:01:33 +00:00
J. Fronny
eb4d7fe2ec Delete main.yml 2020-06-18 20:00:14 +00:00
J. Fronny
fdf8afb388 Update .gitlab-ci.yml 2020-06-18 19:59:55 +00:00
J. Fronny
622d1aa130 Update .gitlab-ci.yml 2020-06-18 19:54:12 +00:00
J. Fronny
4969a420ee Update .gitlab-ci.yml 2020-06-18 19:47:23 +00:00
J. Fronny
f3cb5e136c Update .gitlab-ci.yml 2020-06-18 18:46:14 +00:00
J. Fronny
5cb6fd677a Update .gitlab-ci.yml 2020-06-18 18:40:59 +00:00
J. Fronny
f6644550a6 Update .gitlab-ci.yml 2020-06-18 18:32:38 +00:00
J. Fronny
21ab015742 Update .gitlab-ci.yml 2020-06-18 18:23:05 +00:00
J. Fronny
87b4f3fd08 Update .gitlab-ci.yml 2020-06-18 18:15:20 +00:00
J. Fronny
d7fdd3a711 Update .gitlab-ci.yml 2020-06-18 18:09:19 +00:00
J. Fronny
6b46c7950e Update .gitlab-ci.yml 2020-06-18 17:58:54 +00:00
J. Fronny
db42601eba Update .gitlab-ci.yml 2020-06-18 17:47:33 +00:00
J. Fronny
6b747bdbe8 Update .gitlab-ci.yml 2020-06-18 17:41:37 +00:00
J. Fronny
4dfb57fc2f Add .gitlab-ci.yml 2020-06-18 17:34:06 +00:00
JFronny
7699deb82c Slightly hacky fixes (most likely breaks something) 2020-06-12 19:48:31 +02:00
JFronny
30e27b9a21 No longer broken 2020-06-12 18:24:35 +02:00
JFronny
9e6b441169 ActualSize executes CalculatePosition 2020-06-12 18:16:47 +02:00
JFronny
5d380112ac Run events on all inputs 2020-06-12 16:39:02 +02:00
JFronny
d562ea5295 I am officially stupid 2020-06-12 15:49:38 +02:00
JFronny
4abc39d48b I don't know how it works, I don't want to know but it works so I won't touch it from now 2020-06-12 15:40:08 +02:00
JFronny
b56fb7db78 Remove DiffDraw.FullDraw (merged with DiffDraw.Draw) 2020-06-12 15:21:58 +02:00
JFronny
c5fc9874b1 More null proofing 2020-06-12 15:12:13 +02:00
JFronny
f0400a18bb Maybe fix stack overflow 2020-06-12 14:58:13 +02:00
JFronny
f9e7fb1f40 Fix NullReferenceException in equality operations in Pixel.cs 2020-06-12 14:48:28 +02:00
JFronny
46605e282e Make "Color" property on TUI screen accessible 2020-06-12 14:38:07 +02:00
JFronny
3f35a47e90 Dont draw on title change (prevents NullReferenceException in edge case) 2020-06-12 14:25:24 +02:00
JFronny
94d3ff2873 Prevent DivideByZero if MaxValue and MinValue are equal 2020-06-12 13:02:05 +02:00
JFronny
70fa52a59a Allow MaxValue and MinValue of TUI.Slider to be equal 2020-06-12 12:25:12 +02:00
JFronny
a70f4f4393 Call CalculatePosition if CenteredScreen.Title gets changed 2020-06-12 12:20:04 +02:00
JFronny
fb44579b33 ValueChanged event for TUI Slider 2020-06-12 11:29:07 +02:00
JFronny
79531147b2 Two minor tweaks 2020-06-12 11:24:03 +02:00
JFronny
5f3fb98999 Why where imports broken? 2020-05-25 19:32:53 +02:00
JFronny
f6950a0d4c Centered Screen (like Dialog) and fixes 2020-05-23 17:22:45 +02:00
JFronny
d05f215a62 Document all non-mathematical functions 2020-05-23 15:32:29 +02:00
J. Fronny
bc6d83aa15
Mabe fix 2020-05-22 21:22:46 +02:00
J. Fronny
67b6a35c8a
[ATTEMPT] push CommandLine NuGet 2020-05-22 21:20:51 +02:00
JFronny
11a528766c Simple component system for TUI apps, some basic components 2020-05-22 21:12:09 +02:00
CreepyCrafter24
b73bcce5d5 Add "Parent" property to W32 2020-04-14 14:49:22 +02:00
J. Fronny
d289137096
Possibly fix auto-increment for W32.Test 2020-04-04 16:58:16 +02:00
J. Fronny
d89662666c
Use explicit W32.Test 2020-04-04 16:56:01 +02:00
JFronny
dfe390fffa Maybe fix 2020-04-04 16:45:45 +02:00
JFronny
7f63c58f9b Re-Add some references 2020-04-04 16:42:33 +02:00
JFronny
214f0a53ef Move all WinForms-related code to W32 2020-04-04 16:36:13 +02:00
CreepyCrafter24
1d20e11439 Allow finding window children 2020-04-04 12:22:34 +02:00
CreepyCrafter24
46bfdfe49e Improved window finding 2020-04-04 12:05:42 +02:00
JFronny
1ad691ad99 Add crypto class 2020-04-03 17:32:22 +02:00
JFronny
556996d904 Fix platform check for NET Core 2020-04-03 16:42:31 +02:00
J. Fronny
dcae349716
Update main.yml 2020-04-02 15:39:29 +02:00
J. Fronny
6d3b9c6091
Update README.md 2020-04-01 15:12:42 +02:00
CreepyCrafter24
a3dc105ee6 Merge branch 'master' of https://github.com/JFronny/CC-Functions 2020-03-24 15:56:34 +01:00
CreepyCrafter24
c45b28ed10 Add "Ping" Method 2020-03-24 15:55:49 +01:00
J. Fronny
23dced660d
Update README.md 2020-03-24 15:54:58 +01:00
J. Fronny
fa22f084a8
Some fixes maybe 2020-03-20 16:23:18 +01:00
J. Fronny
98a700f2f2
change Source to s 2020-03-20 16:17:07 +01:00
J. Fronny
456b73633f
Maybe fix NuGet 2020-03-20 16:14:42 +01:00
CreepyCrafter24
88f73c1e10 Add VersionSuffix 2020-03-20 15:13:18 +01:00
J. Fronny
e3cf91ea3b
Add NuGet pushes 2020-03-20 14:53:37 +01:00
CreepyCrafter24
cd298c3b4c Add some NuGet info 2020-03-20 13:52:14 +01:00
CreepyCrafter24
46075b41c4 Change Test-version 2020-03-20 13:41:45 +01:00
CreepyCrafter24
e20ae2556b Some more changes 2020-03-20 13:36:49 +01:00
J. Fronny
61625598c9
Add auto-build 2020-03-20 14:17:01 +01:00
CreepyCrafter24
90394a7708 Some prep for W32 auto-builds 2020-03-20 13:15:16 +01:00
CreepyCrafter24
cce1d2eeb1 Why were these private in the first place? 2020-03-13 19:38:59 +01:00
CreepyCrafter24
0cc87fa5d5 Some additions 2020-03-13 19:19:55 +01:00
CreepyCrafter24
748e5322ab Add mouse events 2020-03-11 18:40:58 +01:00
CreepyCrafter24
023615069c Math extension methods 2020-02-01 21:16:45 +01:00
CreepyCrafter24
da957af741 Added broken Time class, maybe fix Wnd32.Title 2020-02-01 15:32:03 +01:00
CreepyCrafter24
cd89f30f6d Stuffs 2020-01-16 19:50:31 +01:00
CreepyCrafter24
16a91e0ee9 Some improvements 2020-01-15 20:41:52 +01:00
CreepyCrafter24
7d7314b889 Experimental changes to (basically) everything 2020-01-15 17:59:29 +01:00
CreepyCrafter24
d021fec063 Extension methods 2020-01-10 16:58:48 +01:00
CreepyCrafter24
5a4f4c083f No real changes 2020-01-10 16:52:06 +01:00
CreepyCrafter24
1b59434855 Add simple function to get a specified processes main Window as an instance of Wnd32 2020-01-08 17:06:10 +01:00
CreepyCrafter24
2c26188fd9 Added function to get all Wnd32s. This is not recommended but might be useful for some things 2020-01-07 17:59:32 +01:00
CreepyCrafter24
40f88649f1 Minor change 2019-12-30 15:09:16 +01:00
CreepyCrafter24
53a9bc5fe0 Rider+Fix 2019-12-22 16:58:16 +01:00
CreepyCrafter24
2d636f50b7 Ran JetBrains rider and edited slightly to allow HID to be used on linux 2019-12-22 00:29:53 +01:00
CreepyCrafter24
a21a89f051 Allow getting a list of windows, added SelectBox 2019-12-18 17:43:40 +01:00
CreepyCrafter24
8141ae1941 Added DataGridViewUpDown control from GradeCalc 2019-12-18 16:38:08 +01:00
CreepyCrafter24
9d058ede6d Added generic methods for one-liners 2019-11-29 21:42:39 +01:00
CreepyCrafter24
c95f2b8584 Improvements and cleanup 2019-11-29 21:27:24 +01:00
CreepyCrafter24
ef4fadde3b stuffs 2019-11-16 18:27:18 +01:00
CreepyCrafter24
c5aa980b75 Added HID class 2019-11-16 17:59:28 +01:00
CreepyCrafter24
3465a10361 Breaking Change! (Quality fix) 2019-11-10 13:04:27 +01:00
CreepyCrafter24
c8db67a695 Minor Quality improvements 2019-11-10 12:28:29 +01:00
CreepyCrafter24
01abd93de8 Added Input class 2019-10-05 17:52:14 +02:00
CreepyCrafter24
c8496f3baf Some stuffs 2019-10-05 16:37:31 +02:00
CreepyCrafter24
df3afb30b4 Fix 2019-09-11 11:22:16 +02:00
99 changed files with 7182 additions and 1532 deletions

4
.gitignore vendored
View File

@ -1,4 +1,4 @@
CREPLSETUP.creplscript
# Created by https://www.gitignore.io/api/csharp,visualstudio
# Edit at https://www.gitignore.io/?templates=csharp,visualstudio
@ -510,3 +510,5 @@ MigrationBackup/
# Backup folder for Package Reference Convert tool in Visual Studio 2017
# End of https://www.gitignore.io/api/csharp,visualstudio
/.idea/.idea.CC-Functions/.idea/discord.xml
/.idea/.idea.CC-Functions/.idea/contentModel.xml

85
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,85 @@
.shared_windows_runners:
tags:
- windows
image: mcr.microsoft.com/dotnet/sdk
uptool:
extends:
- .shared_windows_runners
stage: deploy
script: |
mkdir i
cd i
$(new-object System.Net.WebClient).DownloadFile("https://gitlab.com/JFronny/UpTool2/-/jobs/artifacts/master/raw/Installer-generic.zip?job=uptool", "$($(pwd).Path)\Install.zip")
& "C:\Program Files\7-Zip\7z.exe" x .\Install.zip
.\Installer.exe --basic i -p
cd ..
rm -R i
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Install"
uptool --basic add-repo DevTools https://gitlab.com/JFronny/UpTool2/-/snippets/2010392/raw
uptool --basic update
uptool --basic install "UpTool2 package tools"
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app"
mkdir .\build
cd W32.Test
dotnet publish -o ..\build -c Release
cd ..
$file = Get-Item $(Resolve-Path .\build\*.exe).Path
pkgtool build --binDir build --mainBin $file --packageFile .\package.zip --noLogo
$asm = $([Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll"))
$asmver = $asm.GetName().Version.ToString()
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = $asm.GetName().Name
$app.appendChild($xml.CreateElement("Description")).InnerText = "Collection of Utilities for manipulating Windows"
$app.appendChild($xml.CreateElement("Version")).InnerText = $asmver
$app.appendChild($xml.CreateElement("ID")).InnerText = "3191d2f3-bf48-48ea-97a2-59fb32722d0a"
$app.appendChild($xml.CreateElement("File")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/package.zip"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\package.zip).Hash
$app.appendChild($xml.CreateElement("MainFile")).InnerText = $file.Name
echo NULL > app.xml
$xml.save($(gi .\app.xml).Fullname)
$tmp1 = $asmver.split('.')[2]
$tmp2 = $asmver.split('.')[3]
$suffix = "$tmp1.$tmp2"
cd Core
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\Misc
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\AspNet
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\W32
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\Commandline
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..
mkdir nugets
cp .\Core\*.nupkg .\nugets\
cp .\Misc\*.nupkg .\nugets\
cp .\W32\*.nupkg .\nugets\
cp .\Commandline\*.nupkg .\nugets\
artifacts:
paths:
- package.zip
- app.xml
- nugets
only:
- master

2
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Default ignored files
/.idea.CC-Functions/.idea/workspace.xml

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelUserStore">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownNavigatorHistory">
<PasteImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
<highlightList />
<directories />
<filenames />
</PasteImageHistory>
<CopyImageHistory checkeredTransparentBackground="false" filename="image" directory="" onPasteImageTargetRef="3" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteReferenceElement="2" cornerRadius="20" borderColor="0" transparentColor="16777215" borderWidth="1" trimTop="0" trimBottom="0" trimLeft="0" trimRight="0" transparent="false" roundCorners="false" showPreview="true" bordered="false" scaled="false" cropped="false" hideInapplicableOperations="false" preserveLinkFormat="false" scale="50" scalingInterpolation="1" transparentTolerance="0" saveAsDefaultOnOK="false" linkFormat="0" addHighlights="false" showHighlightCoordinates="true" showHighlights="false" mouseSelectionAddsHighlight="false" outerFilled="false" outerFillColor="0" outerFillTransparent="true" outerFillAlpha="30">
<highlightList />
<directories />
<filenames />
</CopyImageHistory>
<PasteLinkHistory onPasteImageTargetRef="3" onPasteTargetRef="1" onPasteLinkText="0" onPasteImageElement="1" onPasteLinkElement="1" onPasteWikiElement="2" onPasteReferenceElement="2" hideInapplicableOperations="false" preserveLinkFormat="false" useHeadingForLinkText="false" linkFormat="0" saveAsDefaultOnOK="false" />
<TableToJsonHistory>
<entries />
</TableToJsonHistory>
</component>
</project>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="FlexmarkProjectSettings">
<FlexmarkHtmlSettings flexmarkSpecExampleRendering="0" flexmarkSpecExampleRenderHtml="false">
<flexmarkSectionLanguages>
<option name="1" value="Markdown" />
<option name="2" value="HTML" />
<option name="3" value="flexmark-ast:1" />
</flexmarkSectionLanguages>
</FlexmarkHtmlSettings>
</component>
<component name="MarkdownProjectSettings">
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" synchronizePreviewPosition="true" highlightPreviewType="LINE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="true" showSelectionInPreview="true" lastLayoutSetsDefault="false">
<PanelProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
</PanelProvider>
</PreviewSettings>
<ParserSettings gitHubSyntaxChange="false" emojiShortcuts="0" emojiImages="0">
<PegdownExtensions>
<option name="ABBREVIATIONS" value="false" />
<option name="ANCHORLINKS" value="false" />
<option name="ASIDE" value="false" />
<option name="ATXHEADERSPACE" value="false" />
<option name="AUTOLINKS" value="false" />
<option name="DEFINITIONS" value="false" />
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
<option name="EXTANCHORLINKS" value="false" />
<option name="EXTANCHORLINKS_WRAP" value="false" />
<option name="FENCED_CODE_BLOCKS" value="false" />
<option name="FOOTNOTES" value="false" />
<option name="HARDWRAPS" value="false" />
<option name="HTML_DEEP_PARSER" value="false" />
<option name="INSERTED" value="false" />
<option name="INTELLIJ_DUMMY_IDENTIFIER" value="false" />
<option name="MULTI_LINE_IMAGE_URLS" value="false" />
<option name="QUOTES" value="false" />
<option name="RELAXEDHRULES" value="false" />
<option name="SMARTS" value="false" />
<option name="STRIKETHROUGH" value="false" />
<option name="SUBSCRIPT" value="false" />
<option name="SUPERSCRIPT" value="false" />
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
<option name="SUPPRESS_INLINE_HTML" value="false" />
<option name="TABLES" value="false" />
<option name="TASKLISTITEMS" value="false" />
<option name="TOC" value="false" />
<option name="WIKILINKS" value="false" />
</PegdownExtensions>
<ParserOptions>
<option name="ADMONITION_EXT" value="false" />
<option name="ATTRIBUTES_EXT" value="false" />
<option name="COMMONMARK_LISTS" value="false" />
<option name="DUMMY" value="false" />
<option name="EMOJI_SHORTCUTS" value="false" />
<option name="ENUMERATED_REFERENCES_EXT" value="false" />
<option name="FLEXMARK_FRONT_MATTER" value="false" />
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
<option name="GFM_TABLE_RENDERING" value="false" />
<option name="GITBOOK_URL_ENCODING" value="false" />
<option name="GITHUB_LISTS" value="false" />
<option name="GITHUB_WIKI_LINKS" value="false" />
<option name="GITLAB_EXT" value="false" />
<option name="GITLAB_MATH_EXT" value="false" />
<option name="GITLAB_MERMAID_EXT" value="false" />
<option name="HEADER_ID_NON_ASCII_TO_LOWERCASE" value="false" />
<option name="HEADER_ID_NO_DUPED_DASHES" value="false" />
<option name="JEKYLL_FRONT_MATTER" value="false" />
<option name="MACROS_EXT" value="false" />
<option name="NO_TEXT_ATTRIBUTES" value="false" />
<option name="PARSE_HTML_ANCHOR_ID" value="false" />
<option name="PLANTUML_FENCED_CODE" value="false" />
<option name="PRODUCTION_SPEC_PARSER" value="false" />
<option name="PUML_FENCED_CODE" value="false" />
<option name="SIM_TOC_BLANK_LINE_SPACER" value="false" />
<option name="SPACE_IN_LINK_URLS" value="false" />
</ParserOptions>
</ParserSettings>
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" addPageHeader="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0">
<GeneratorProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.text.html.generator" providerName="Unmodified HTML Generator" />
</GeneratorProvider>
<headerTop />
<headerBottom />
<bodyTop />
<bodyBottom />
</HtmlSettings>
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
<StylesheetProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.text.html.css" providerName="No Stylesheet" />
</StylesheetProvider>
<ScriptProviders />
<cssText />
<cssUriHistory />
</CssSettings>
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.CC-Functions/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.CC-Functions/riderModule.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

33
AspNet/AspNet.csproj Normal file
View File

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>CC_Functions.AspNet</RootNamespace>
<AssemblyName>CC_Functions.AspNet</AssemblyName>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.AspNet</PackageId>
<Title>CC-Functions.AspNet</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code for Asp.Net, including my SerialDict integrated Database</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Core.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DocumentationFile>bin\Release\Core.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="protobuf-net" Version="3.0.62" />
<PackageReference Include="System.Text.Json" Version="5.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace CC_Functions.AspNet
{
/// <summary>
/// Provides serializing dictionary with Guid keys
/// </summary>
public class DictionaryGuidConverter : JsonConverterFactory
{
/// <inheritdoc />
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType)
{
return false;
}
if (typeToConvert.GetGenericTypeDefinition() != typeof(Dictionary<,>))
{
return false;
}
return typeToConvert.GetGenericArguments()[0] == typeof(Guid);
}
/// <inheritdoc />
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type valueType = typeToConvert.GetGenericArguments()[1];
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(DictionaryGuidConverterInner<>).MakeGenericType(valueType),
BindingFlags.Instance | BindingFlags.Public,
null,
new object[] { options },
null);
return converter;
}
private class DictionaryGuidConverterInner<TValue> : JsonConverter<Dictionary<Guid, TValue>>
{
private readonly JsonConverter<TValue> _valueConverter;
private Type _valueType;
public DictionaryGuidConverterInner(JsonSerializerOptions options)
{
// For performance, use the existing converter if available.
_valueConverter = (JsonConverter<TValue>)options
.GetConverter(typeof(TValue));
// Cache the key and value types.
_valueType = typeof(TValue);
}
public override Dictionary<Guid, TValue> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
Dictionary<Guid, TValue> dictionary = new Dictionary<Guid, TValue>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return dictionary;
}
// Get the key.
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException();
}
string propertyName = reader.GetString();
// For performance, parse with ignoreCase:false first.
if (!Guid.TryParse(propertyName, out Guid key))
{
throw new JsonException(
$"Unable to convert \"{propertyName}\" to Guid.");
}
// Get the value.
TValue v;
if (_valueConverter != null)
{
reader.Read();
v = _valueConverter.Read(ref reader, _valueType, options);
}
else
{
v = JsonSerializer.Deserialize<TValue>(ref reader, options);
}
// Add to dictionary.
dictionary.Add(key, v);
}
throw new JsonException();
}
public override void Write(
Utf8JsonWriter writer,
Dictionary<Guid, TValue> dictionary,
JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (KeyValuePair<Guid, TValue> kvp in dictionary)
{
writer.WritePropertyName(kvp.Key.ToString());
if (_valueConverter != null)
{
_valueConverter.Write(writer, kvp.Value, options);
}
else
{
JsonSerializer.Serialize(writer, kvp.Value, options);
}
}
writer.WriteEndObject();
}
}
}
}

View File

@ -0,0 +1,21 @@
using System.Text.Json;
namespace CC_Functions.AspNet
{
/// <summary>
/// Extension methods for various types
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Include CCF json extensions for this serializer
/// </summary>
/// <param name="options">The options to include CCF in</param>
/// <returns>The options including CCF</returns>
public static JsonSerializerOptions AddCcf(this JsonSerializerOptions options)
{
options.Converters.Add(new DictionaryGuidConverter());
return options;
}
}
}

164
AspNet/SaveLoadDict.cs Normal file
View File

@ -0,0 +1,164 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace CC_Functions.AspNet
{
/// <summary>
/// Provides synchronizing for dictionaries with saving/loading backends
/// </summary>
/// <typeparam name="T">The key type</typeparam>
/// <typeparam name="U">The param type</typeparam>
public abstract class SaveLoadDict<T, U> : IDictionary<T, U>
{
/// <inheritdoc />
public IEnumerator<KeyValuePair<T, U>> GetEnumerator()
{
lock (this) return Load().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
lock (this) return GetEnumerator();
}
/// <inheritdoc />
public void Add(KeyValuePair<T, U> item)
{
lock (this) Add(item.Key, item.Value);
}
/// <inheritdoc />
public void Clear()
{
lock (this) Save(new Dictionary<T, U>());
}
/// <inheritdoc />
public bool Contains(KeyValuePair<T, U> item)
{
lock (this) return Load().Contains(item);
}
/// <inheritdoc />
public void CopyTo(KeyValuePair<T, U>[] array, int arrayIndex)
{
lock (this) Load().CopyTo(array, arrayIndex);
}
/// <inheritdoc />
public bool Remove(KeyValuePair<T, U> item)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
try
{
return dictionary.Remove(item);
}
finally
{
Save(dictionary);
}
}
}
/// <inheritdoc />
public int Count
{
get { lock (this) return Load().Count; }
}
/// <inheritdoc />
public bool IsReadOnly => false;
/// <inheritdoc />
public void Add(T key, U value)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
dictionary.Add(key, value);
Save(dictionary);
}
}
/// <inheritdoc />
public bool ContainsKey(T key)
{
lock (this) return Load().ContainsKey(key);
}
/// <inheritdoc />
public bool Remove(T key)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
try
{
return dictionary.Remove(key);
}
finally
{
Save(dictionary);
}
}
}
/// <inheritdoc />
public bool TryGetValue(T key, out U value)
{
lock (this) return Load().TryGetValue(key, out value);
}
/// <inheritdoc />
public U this[T key]
{
get
{
lock (this) return Load()[key];
}
set
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
dictionary[key] = value;
Save(dictionary);
}
}
}
/// <inheritdoc />
public ICollection<T> Keys
{
get { lock (this) return Load().Keys; }
}
/// <inheritdoc />
public ICollection<U> Values
{
get { lock (this) return Load().Values; }
}
/// <summary>
/// Replace the current content based on the current state
/// </summary>
/// <param name="f">Function to mutate the content</param>
public void Mutate(Func<IDictionary<T, U>, IDictionary<T, U>> f)
{
lock (this) Save(f(Load()));
}
/// <summary>
/// Save the dictionary content
/// </summary>
/// <param name="v">Dictionary content to save</param>
protected abstract void Save(IDictionary<T, U> v);
/// <summary>
/// Load the content to a dictionary
/// </summary>
/// <returns>The loaded content</returns>
protected abstract IDictionary<T, U> Load();
}
}

73
AspNet/SerialDict.cs Normal file
View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ProtoBuf;
namespace CC_Functions.AspNet
{
/// <summary>
/// An implementation of SaveLoadDict that uses Protobuf-net for serialization and Guid keys
/// </summary>
/// <typeparam name="T">The data type</typeparam>
public abstract class SerialDict<T> : SaveLoadDict<Guid, T>
{
//Interface
/// <summary>
/// Gets the directory containing databases
/// </summary>
public abstract string DatabasesDir { get; }
/// <summary>
/// Gets the file name for this database. Must not contain the path
/// </summary>
public abstract string DatabaseFileName { get; }
/// <summary>
/// Called when the database is loaded. Use for preparing initial entries
/// </summary>
public event LoadedD Loaded;
/// <summary>
/// Called when the database is loaded. Use for preparing initial entries
/// </summary>
/// <param name="v">The current dictionary content</param>
public delegate void LoadedD(IDictionary<Guid, T> v);
/// <summary>
/// Loads the dictionary and replaces Guids with strings. Use for sending
/// </summary>
/// <returns>The simplified dictionary</returns>
public IDictionary<string, T> GetSendable() => Load().ToDictionary(s => s.Key.ToString(), s => s.Value);
//Internal
private string GetRel() => Path.Combine(DatabasesDir, DatabaseFileName);
/// <inheritdoc />
protected override IDictionary<Guid, T> Load()
{
if (!Directory.Exists(DatabasesDir))
Directory.CreateDirectory(DatabasesDir);
IDictionary<Guid, T> v;
if (File.Exists(GetRel()))
{
using (FileStream file = File.OpenRead(GetRel()))
v = Serializer.Deserialize<Dictionary<Guid, T>>(file);
Loaded?.Invoke(v);
return v;
}
else
{
v = new Dictionary<Guid, T>();
Loaded?.Invoke(v);
Save(v);
return v;
}
}
/// <inheritdoc />
protected override void Save(IDictionary<Guid, T> dict)
{
if (!Directory.Exists(DatabasesDir))
Directory.CreateDirectory(DatabasesDir);
using FileStream file = File.Create(GetRel());
Serializer.Serialize(file, dict);
}
}
}

View File

@ -9,6 +9,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Misc", "Misc\Misc.csproj",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "W32.Test", "W32.Test\W32.Test.csproj", "{6121A6D3-7C73-4EDE-A5A9-09DC52150824}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commandline", "Commandline\Commandline.csproj", "{08C16A0B-A69D-4229-BC6D-F6949CA7BE76}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLITest", "CLITest\CLITest.csproj", "{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{780EC190-E223-46DE-B6FB-1CF56ABDF34E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNet", "AspNet\AspNet.csproj", "{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -27,6 +35,22 @@ Global
{6121A6D3-7C73-4EDE-A5A9-09DC52150824}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6121A6D3-7C73-4EDE-A5A9-09DC52150824}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6121A6D3-7C73-4EDE-A5A9-09DC52150824}.Release|Any CPU.Build.0 = Release|Any CPU
{08C16A0B-A69D-4229-BC6D-F6949CA7BE76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08C16A0B-A69D-4229-BC6D-F6949CA7BE76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08C16A0B-A69D-4229-BC6D-F6949CA7BE76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08C16A0B-A69D-4229-BC6D-F6949CA7BE76}.Release|Any CPU.Build.0 = Release|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Release|Any CPU.Build.0 = Release|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Release|Any CPU.Build.0 = Release|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

13
CLITest/CLITest.csproj Normal file
View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>8</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Commandline\Commandline.csproj" />
</ItemGroup>
</Project>

108
CLITest/Program.cs Normal file
View File

@ -0,0 +1,108 @@
using System;
using System.Drawing;
using System.Threading;
using CC_Functions.Commandline;
using CC_Functions.Commandline.TUI;
using CC_Functions.Core;
namespace CLITest
{
internal class Program
{
private static void Main()
{
Thread.CurrentThread.ForceInvariantCulture();
//Parse test
if (new ArgsParse(new[] { "--meme", "Fuk u", "--meme:yeet", "--meme:yote", "--meme" })["meme"] != "yote")
throw new Exception("ArgsParse error 1");
if (!new ArgsParse(new[] { "--meme", "Fuk u", "--meme:yeet", "--meme:yote", "--meme" }).GetBool("meme"))
throw new Exception("ArgsParse error 2");
if (new ArgsParse(new[] {"--meme:"}).GetBool("meme"))
throw new Exception("ArgsParse error 3");
if (!new ArgsParse(new[] {"--meme:true"}).GetBool("mEme"))
throw new Exception("ArgsParse error 4");
if (new ArgsParse(new[] {"--meme:1.1.2019"}).Get<DateTime>("meme") != new DateTime(2019, 1, 1))
throw new Exception("ArgsParse error 5");
if (new ArgsParse(new[] {"--meme:2019"}).Get("meme", s => s == null ? DateTime.Now : DateTime.Parse("1.1." + s)) != new DateTime(2019, 1, 1))
throw new Exception("ArgsParse error 6");
//Display test
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
Console.Clear();
CenteredScreen cScreen = new CenteredScreen(40, 20, ConsoleColor.Green);
Panel screen = cScreen.ContentPanel;
Button btn1 = new Button("Test")
{
Point = new Point(2, 0),
BackColor = ConsoleColor.DarkGreen
};
screen.Controls.Add(btn1);
btn1.Click += (screen1, eventArgs) => { DiffDraw.Draw(true, true); };
Label lab1 = new Label("Meem")
{
Point = new Point(2, 1),
BackColor = ConsoleColor.Green
};
screen.Controls.Add(lab1);
screen.Controls.Add(new Label("Saas\nSoos")
{
Point = new Point(2, 2),
BackColor = ConsoleColor.Green
});
Button btn2 = new Button("X")
{
BackColor = ConsoleColor.Red,
ForeColor = ConsoleColor.White
};
screen.Controls.Add(btn2);
CheckBox box = new CheckBox("Are u gae?")
{
Point = new Point(2, 3),
BackColor = ConsoleColor.DarkGreen
};
screen.Controls.Add(box);
box.CheckedChanged += (screen1, eventArgs) => { lab1.Content = box.Checked ? "Sas" : "Meem"; };
TextBox tbox = new TextBox("Hello\nWorld1\n\nHow are u?")
{
Size = new Size(20, 10),
Point = new Point(0, 6),
BackColor = ConsoleColor.DarkYellow
};
screen.Controls.Add(tbox);
Slider slider = new Slider
{
Point = new Point(2, 4),
Size = new Size(16, 2),
MaxValue = 75,
StepSize = 14,
MinValue = -3,
Value = 7,
BackColor = ConsoleColor.Magenta
};
screen.Controls.Add(slider);
bool visible = true;
btn2.Click += (screen1, eventArgs) => visible = false;
cScreen.Close += (screen1, eventArgs) => visible = false;
cScreen.TabChanged += (screen1, eventArgs) => btn1.Content = $"Test {cScreen.TabPoint}";
cScreen.Render();
while (visible)
{
Thread.Sleep(50);
cScreen.ReadInput();
}
Console.ResetColor();
Console.Clear();
Console.WriteLine("Test2");
Thread.Sleep(100);
DiffDraw.Clear(10, 10);
DiffDraw.Draw(true, false);
Console.Clear();
Console.WriteLine("Bye");
}
}
}

98
Commandline/ArgsParse.cs Normal file
View File

@ -0,0 +1,98 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
namespace CC_Functions.Commandline
{
/// <summary>
/// A class to provide basic parsing for program arguments
/// </summary>
public class ArgsParse : IEnumerable<string>
{
private readonly string[] _args;
/// <summary>
/// Create a new instance based on the specified args
/// </summary>
/// <param name="args">The inputted args. Should be a parameter of the main method</param>
public ArgsParse(string[] args) => _args = args ?? throw new NullReferenceException();
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <param name="i">The index in the base args</param>
public string this[int i]
{
get => _args[i];
set => _args[i] = value;
}
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <returns>An enumerator for the base args</returns>
IEnumerator<string> IEnumerable<string>.GetEnumerator() => ((IEnumerable<string>)_args).GetEnumerator();
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator() => _args.GetEnumerator();
/// <summary>
/// Gets the string specified for this key or null
/// </summary>
/// <param name="i">The name of the parameter</param>
public string? this[string i]
{
get
{
string? selected = null;
foreach (string s in _args)
if (s.TrimStart('-', '/').ToLower().StartsWith($"{i.ToLower()}:"))
selected = string.Join("", s.TrimStart('-', '/').Skip(i.Length + 1));
return selected;
}
}
/// <summary>
/// Gets the string specified for this key or null
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <returns>The value or null</returns>
public string? GetString(string i) => this[i];
/// <summary>
/// Gets a boolean value with the specified name. Either specified as --i or --i:true
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <returns>The value</returns>
public bool GetBool(string i) => _args.Any(s => s.ToLower().TrimStart('-', '/') == i.ToLower()) || bool.TryParse(this[i], out bool res) && res;
/// <summary>
/// Gets an arg using a transformer specified by you. The value passed will be the same as this[i]
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <param name="func">A null-safe function to convert a string to the expected type</param>
/// <typeparam name="T">The type to convert to</typeparam>
/// <returns>The converted value</returns>
public T Get<T>(string i, Func<string?, T> func) => func(this[i]);
/// <summary>
/// Uses reflection to call the Parse method on types providing it. Use Get() with a func param for other types
/// This will return null if the type is not found
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <typeparam name="T">The type to convert to</typeparam>
/// <returns>The converted value</returns>
public T Get<T>(string i)
{
MethodInfo[] parse = typeof(T).GetMethods().Where(s => s.Name.ToLower() == "parse"
&& s.GetParameters().Length == 1
&& s.GetParameters()[0].ParameterType == typeof(string)
&& s.ReturnType == typeof(T)
&& !s.IsAbstract && !s.IsPrivate && s.IsStatic).ToArray();
if (parse.Length == 0)
throw new InvalidOperationException("Could not find a valid parse method");
string? v = this[i];
if (v == null)
return default;
return (T) parse[0].Invoke(null, new object[] {v});
}
}
}

View File

@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>CC_Functions.Commandline</RootNamespace>
<AssemblyName>CC_Functions.Commandline</AssemblyName>
<LangVersion>8</LangVersion>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Commandline</PackageId>
<Title>CC-Functions.Commandline</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code used across my projects. CLI/TUI extensions</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DocumentationFile>bin\Debug\Commandline.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\Commandline.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
</Project>

150
Commandline/DiffDraw.cs Normal file
View File

@ -0,0 +1,150 @@
using System;
using System.Drawing;
using CC_Functions.Commandline.TUI;
using CC_Functions.Core;
namespace CC_Functions.Commandline
{
/// <summary>
/// Provides differential drawing of a char[,] Do not use in combination with System.Console
/// </summary>
public static class DiffDraw
{
private static Pixel[,] _last = new Pixel[0, 0];
private static Pixel[,] Screen { get; set; } = new Pixel[0, 0];
/// <summary>
/// The regions width
/// </summary>
public static int Width => Screen.GetLength(1);
/// <summary>
/// The regions height
/// </summary>
public static int Height => Screen.GetLength(0);
/// <summary>
/// Draws to the console
/// </summary>
/// <param name="color">Whether to use color</param>
/// <param name="full">Whether to redraw the entire screen (should be done from time to time to prevent corruption)</param>
public static void Draw(bool color, bool full = false)
{
Console.CursorTop = 0;
Console.CursorLeft = 0;
ConsoleColor fCol = Console.ForegroundColor;
ConsoleColor bCol = Console.BackgroundColor;
if (full) Console.Clear();
int width = Width;
int height = Height;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Pixel tmp1 = Screen[y, x];
if (!full && tmp1 == _last[y, x]) continue;
if (!ReferenceEquals(tmp1, null) && color)
{
if (Console.ForegroundColor != tmp1.ForeColor)
Console.ForegroundColor = tmp1.ForeColor;
if (Console.BackgroundColor != tmp1.BackColor)
Console.BackgroundColor = tmp1.BackColor;
}
Console.CursorLeft = x;
Console.Write(tmp1 ?? Pixel.Empty);
}
Console.WriteLine();
Console.CursorLeft = 0;
}
Console.ForegroundColor = fCol;
Console.BackgroundColor = bCol;
_last = Screen;
}
/// <summary>
/// Gets the char at a location
/// </summary>
/// <param name="p">The location</param>
/// <returns>The char</returns>
public static char Get(Point p) => Get(p.X, p.Y);
/// <summary>
/// Gets the char at a location
/// </summary>
/// <param name="x">The locations X coordinate</param>
/// <param name="y">The locations Y coordinate</param>
/// <returns>The char</returns>
public static char Get(int x, int y) => Screen[y, x].Content;
/// <summary>
/// Gets the foreground color at a location
/// </summary>
/// <param name="p">The location</param>
/// <returns>The color</returns>
public static ConsoleColor GetForeColor(Point p) => GetForeColor(p.X, p.Y);
/// <summary>
/// Gets the foreground color at a location
/// </summary>
/// <param name="x">The locations X coordinate</param>
/// <param name="y">The locations Y coordinate</param>
/// <returns>The color</returns>
public static ConsoleColor GetForeColor(int x, int y) => Screen[y, x].ForeColor;
/// <summary>
/// Gets the background color at a location
/// </summary>
/// <param name="p">The location</param>
/// <returns>The color</returns>
public static ConsoleColor GetBackColor(Point p) => GetBackColor(p.X, p.Y);
/// <summary>
/// Gets the background color at a location
/// </summary>
/// <param name="x">The locations X coordinate</param>
/// <param name="y">The locations Y coordinate</param>
/// <returns>The color</returns>
public static ConsoleColor GetBackColor(int x, int y) => Screen[y, x].BackColor;
/// <summary>
/// Sets a pixel at a point
/// </summary>
/// <param name="p">The point to place at</param>
/// <param name="c">The pixel to place</param>
public static void Set(Point p, Pixel c) => Set(p.X, p.Y, c);
/// <summary>
/// Sets a pixel at a location
/// </summary>
/// <param name="x">The locations X coordinate</param>
/// <param name="y">The locations Y coordinate</param>
/// <param name="c">The pixel to place</param>
public static void Set(int x, int y, Pixel c) => Screen[y, x] = c;
/// <summary>
/// Clears the screen
/// </summary>
public static void Clear() => Clear(Width, Height);
/// <summary>
/// Resizes and clears the screen
/// </summary>
/// <param name="width">The new width</param>
/// <param name="height">The new height</param>
public static void Clear(int width, int height)
{
Screen = new Pixel[height, width];
_last = _last.Resize(height, width);
}
/// <summary>
/// Replaces the screen state
/// </summary>
/// <param name="content">The new state</param>
public static void Clear(Pixel[,] content)
{
Screen = content;
_last = _last.Resize(Height, Width);
}
}
}

67
Commandline/TUI/Button.cs Normal file
View File

@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// A basic button type
/// </summary>
public class Button : Control
{
/// <summary>
/// The text inside this button
/// </summary>
public string Content;
/// <summary>
/// Creates a new button
/// </summary>
/// <param name="content">The text inside this button</param>
public Button(string content)
{
Content = content;
char[,] tmp = Content.ToNdArray2D();
Size = new Size(tmp.GetLength(1), tmp.GetLength(0));
}
/// <inheritdoc />
public override bool Selectable { get; } = true;
/// <inheritdoc />
public override Pixel[,] Render()
{
char[,] inp = Indent(SplitLines(Content, Size.Width), Size.Width).ToNdArray2D();
inp = inp.Resize(Size.Height, Size.Width);
Pixel[,] output = new Pixel[Size.Height, Size.Width];
for (int x = 0; x < Size.Height; x++)
for (int y = 0; y < Size.Width; y++)
output[x, y] = new Pixel(Selected ? ForeColor : BackColor, Selected ? BackColor : ForeColor, inp[x, y]);
return output;
}
private string Indent(string source, int maxLen)
{
string[] tmp = source.Split('\n');
for (int i = 0; i < tmp.Length; i++) tmp[i] = new string(SpecialChars.Empty, (maxLen - tmp[i].Length) / 2) + tmp[i];
return string.Join('\n', tmp);
}
private string SplitLines(string source, int maxLen)
{
List<string> parts = new List<string>(source.Split());
while (parts.Any(s => s.Length > maxLen))
{
parts = parts.SelectMany(s =>
{
if (s.Length > maxLen)
return s.Insert(maxLen, "\n").Split('\n');
else
return new[] {s};
}).ToList();
}
return string.Join('\n', parts);
}
}
}

View File

@ -0,0 +1,97 @@
using System;
using System.Drawing;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Provides a screen that stays in the middle of the console. Use ContentPanel to attach controls
/// </summary>
public class CenteredScreen : Screen
{
private bool _resizing;
private Size _actualSize;
/// <summary>
/// The panel used for storing and rendering the actual controls
/// </summary>
public Panel ContentPanel;
private string _title = "CC-Functions.CommandLine app";
private readonly Label _titleLabel;
/// <summary>
/// Creates a screen that stays in the middle of the console. Use ContentPanel to attach controls
/// </summary>
/// <param name="width">The width of the content panel</param>
/// <param name="height">The height of the content panel</param>
/// <param name="contentBack">The content panels background (Should be different from Console.BackgroundColor)</param>
/// <param name="color">Whether to use color when drawing</param>
public CenteredScreen(int width, int height, ConsoleColor contentBack, bool color = true) : base(width, height, color)
{
_titleLabel = new Label(Title);
ContentPanel = new Panel {BackColor = contentBack};
ActualSize = new Size(width, height);
Controls.Add(ContentPanel);
Controls.Add(_titleLabel);
WindowResize += (screen, args) => CalculatePosition();
((Control) this).Resize += (caller, args) => CalculatePosition();
CalculatePosition(true);
}
/// <summary>
/// The title to display at the top of the console
/// </summary>
public string Title
{
get => _title;
set
{
if (_title != value && !string.IsNullOrWhiteSpace(value))
{
_title = value;
CalculatePosition(true);
}
}
}
/// <summary>
/// The actual size of this control. The "Size" property is assigned automatically
/// </summary>
public Size ActualSize
{
get => _actualSize;
set
{
if (_actualSize != value)
{
_actualSize = value;
CalculatePosition(true);
}
}
}
/// <summary>
/// Calculates the Size variable, Title and ContentPanel position/size
/// </summary>
/// <param name="initial">Whether this is the initial calculation</param>
public void CalculatePosition(bool initial = false)
{
if (!_resizing)
{
_resizing = true;
Size = new Size(Console.WindowWidth, Console.WindowHeight - 1);
_titleLabel.Content = Title + Environment.NewLine + new string(SpecialChars.OneLineSimple.LeftRight, Console.WindowWidth);
ContentPanel.Size = ActualSize;
ContentPanel.Point = new Point((Console.WindowWidth - ActualSize.Width) / 2,
(Console.WindowHeight - ActualSize.Height) / 2);
if (!initial)
{
Console.Clear();
DiffDraw.Draw(Color, true);
}
_resizing = false;
}
}
}
}

View File

@ -0,0 +1,83 @@
using System;
using System.Drawing;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Provides a control for users to select a boolean
/// </summary>
public class CheckBox : Control
{
/// <summary>
/// Called when the state of this checkbox is changed
/// </summary>
/// <param name="screen">The current screen instance</param>
/// <param name="e">Args</param>
public delegate void OnCheckedChanged(Screen screen, EventArgs e);
/// <summary>
/// Whether the box is checked
/// </summary>
public bool Checked;
/// <summary>
/// The text inside this checkbox
/// </summary>
public string Content;
/// <summary>
/// Creates a new checkbox
/// </summary>
/// <param name="content">The text inside this CheckBox</param>
public CheckBox(string content)
{
Content = content;
Input += (screen, args) =>
{
switch (args.Info.Key)
{
case ConsoleKey.LeftArrow:
case ConsoleKey.RightArrow:
case ConsoleKey.Spacebar:
Checked = !Checked;
CheckedChanged?.Invoke(screen, args);
break;
}
};
Click += (screen, args) =>
{
Checked = !Checked;
CheckedChanged?.Invoke(screen, args);
};
}
/// <inheritdoc />
public override bool Selectable { get; } = true;
/// <inheritdoc />
public override Pixel[,] Render()
{
char[,] inp1 = Content.ToNdArray2D();
char[,] inp = new char[inp1.GetLength(0), inp1.GetLength(1) + 4];
inp.Populate(' ');
inp1.CopyTo(inp, new Point(4, 0));
inp[0, 0] = '[';
inp[0, 1] = Checked ? 'X' : SpecialChars.Empty;
inp[0, 2] = ']';
int w = inp.GetLength(0);
int h = inp.GetLength(1);
Pixel[,] output = new Pixel[w, h];
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
output[x, y] = new Pixel(Selected ? ForeColor : BackColor, Selected ? BackColor : ForeColor, inp[x, y]);
Size = new Size(w, h);
return output;
}
/// <summary>
/// Called when the state of this checkbox is changed
/// </summary>
public event OnClick CheckedChanged;
}
}

125
Commandline/TUI/Control.cs Normal file
View File

@ -0,0 +1,125 @@
using System;
using System.Drawing;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Abstract class inherited by all controls
/// </summary>
public abstract class Control
{
/// <summary>
/// Called when [enter] is pressed while the control is selected
/// </summary>
/// <param name="screen">An instance of the calling screen</param>
/// <param name="e">Args</param>
public delegate void OnClick(Screen screen, EventArgs e);
/// <summary>
/// Called when the control is selected and unknown input is given
/// </summary>
/// <param name="screen">An instance of the calling screen</param>
/// <param name="e">Args</param>
public delegate void OnInput(Screen screen, InputEventArgs e);
/// <summary>
/// Called when the controls Size property is changed
/// </summary>
/// <param name="caller">The calling control</param>
/// <param name="e">Args</param>
public delegate void OnResize(Control caller, EventArgs e);
private Size _size;
/// <summary>
/// Whether the control can be interacted with
/// </summary>
public bool Enabled = true;
/// <summary>
/// Whether the control should be rendered
/// </summary>
public bool Visible = true;
/// <summary>
/// The size of the control
/// </summary>
public Size Size
{
set
{
if (_size != value)
{
_size = value;
Resize?.Invoke(this, new EventArgs());
}
}
get => _size;
}
/// <summary>
/// The position of this control
/// </summary>
public Point Point { get; set; }
/// <summary>
/// The foreground color for this control
/// </summary>
public ConsoleColor ForeColor { get; set; } = Console.ForegroundColor;
/// <summary>
/// The background color for this control
/// </summary>
public ConsoleColor BackColor { get; set; } = Console.BackgroundColor;
/// <summary>
/// Whether the control can be selected
/// </summary>
public abstract bool Selectable { get; }
/// <summary>
/// Whether the object is selected. Used internally and for drawing
/// </summary>
public bool Selected { get; internal set; } = false;
/// <summary>
/// Called when the controls Size property is changed
/// </summary>
public event OnResize Resize;
/// <summary>
/// Renders the control
/// </summary>
/// <returns>The rendered pixels</returns>
public abstract Pixel[,] Render();
/// <summary>
/// Called when [enter] is pressed while the control is selected
/// </summary>
public event OnClick Click;
/// <summary>
/// Called when the control is selected and unknown input is given
/// </summary>
public event OnInput Input;
/// <summary>
/// Invokes click events
/// </summary>
/// <param name="screen">The calling screen</param>
internal void InvokeClick(Screen screen)
{
Click?.Invoke(screen, new EventArgs());
}
/// <summary>
/// Invokes input events
/// </summary>
/// <param name="screen">The calling screen</param>
/// <param name="info">The input data</param>
internal void InvokeInput(Screen screen, ConsoleKeyInfo info)
{
Input?.Invoke(screen, new InputEventArgs(info));
}
}
}

View File

@ -0,0 +1,21 @@
using System;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Arguments containing input data
/// </summary>
public class InputEventArgs : EventArgs
{
/// <summary>
/// Generates new arguments
/// </summary>
/// <param name="info">The input data</param>
public InputEventArgs(ConsoleKeyInfo info) => Info = info;
/// <summary>
/// The inputs data
/// </summary>
public ConsoleKeyInfo Info { get; }
}
}

58
Commandline/TUI/Label.cs Normal file
View File

@ -0,0 +1,58 @@
using System.Drawing;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// A basic text control
/// </summary>
public class Label : Control
{
private string _content;
/// <summary>
/// Creates a new label
/// </summary>
/// <param name="content">The text inside this label</param>
public Label(string content)
{
_content = "";
Content = content;
}
/// <inheritdoc />
public override bool Selectable { get; } = false;
/// <summary>
/// The text inside this label
/// </summary>
public string Content
{
get => _content;
set
{
if (_content != value)
{
_content = value;
char[,] inp = Content.ToNdArray2D();
int w = inp.GetLength(1);
int h = inp.GetLength(0);
Size = new Size(w, h);
}
}
}
/// <inheritdoc />
public override Pixel[,] Render()
{
char[,] inp = Content.ToNdArray2D();
int w = inp.GetLength(0);
int h = inp.GetLength(1);
Pixel[,] output = new Pixel[w, h];
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
output[x, y] = new Pixel(BackColor, ForeColor, inp[x, y]);
return output;
}
}
}

63
Commandline/TUI/Panel.cs Normal file
View File

@ -0,0 +1,63 @@
using System.Collections.Generic;
using System.Linq;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// A panel containing other components. MUST be inherited for all other controls that contain others
/// </summary>
public class Panel : Control
{
/// <summary>
/// Enable to draw a simple border around this control
/// </summary>
public bool Border = true;
/// <summary>
/// The controls inside this panel
/// </summary>
public List<Control> Controls = new List<Control>();
/// <inheritdoc />
public override bool Selectable { get; } = false;
/// <summary>
/// Renders the control and all contained controls
/// </summary>
/// <returns>The rendered pixels</returns>
public override Pixel[,] Render()
{
Pixel[,] tmp = new Pixel[Size.Height, Size.Width];
tmp.Populate(new Pixel(BackColor, ForeColor, SpecialChars.Empty));
if (Border)
{
for (int i = 0; i < Size.Width; i++) tmp[Size.Height - 1, i] = new Pixel(BackColor, ForeColor, SpecialChars.OneLineSimple.LeftRight);
for (int i = 0; i < Size.Height; i++) tmp[i, Size.Width - 1] = new Pixel(BackColor, ForeColor, SpecialChars.OneLineSimple.UpDown);
tmp[Size.Height - 1, Size.Width - 1] = new Pixel(BackColor, ForeColor, '┘');
}
foreach (Control control in Controls)
if (control.Visible)
{
Pixel[,] render = control.Render();
render.CopyTo(tmp, control.Point);
}
return tmp;
}
/// <summary>
/// Recursively enumerates all controls
/// </summary>
/// <returns>A list of all controls</returns>
public Control[] EnumerateRecursive()
{
List<Control> output = Controls.ToList();
int i = 0;
while (i < output.Count)
{
if (output[i] is Panel p) output.AddRange(p.EnumerateRecursive().Where(s => !output.Contains(s)));
i++;
}
return output.ToArray();
}
}
}

123
Commandline/TUI/Pixel.cs Normal file
View File

@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Represents a pixel
/// </summary>
public class Pixel
{
public static readonly Pixel Empty = new Pixel();
/// <summary>
/// This pixels background color
/// </summary>
public ConsoleColor BackColor;
/// <summary>
/// This pixels content character
/// </summary>
public char Content;
/// <summary>
/// This pixels foregound color
/// </summary>
public ConsoleColor ForeColor;
/// <summary>
/// Generates a new pixel
/// </summary>
/// <param name="backColor">The background color</param>
/// <param name="foreColor">The foreground color</param>
/// <param name="content">The new content</param>
public Pixel(ConsoleColor backColor, ConsoleColor foreColor, char content)
{
BackColor = backColor;
ForeColor = foreColor;
Content = content;
}
/// <summary>
/// Generates a new pixel
/// </summary>
/// <param name="content">The content for this pixel</param>
public Pixel(char content) : this(Console.BackgroundColor, Console.ForegroundColor, content)
{
}
/// <summary>
/// Generates a new pixel
/// </summary>
public Pixel() : this(' ')
{
}
/// <summary>
/// Use this in functions that require equality comparers
/// </summary>
public static IEqualityComparer<Pixel> ColorContentComparer { get; } = new ColorContentEqualityComparer();
/// <summary>
/// Whether this is equal to another pixel
/// </summary>
/// <param name="other">The other pixel to compare</param>
/// <returns>Whether they are equal</returns>
protected bool Equals(Pixel other) => ColorContentComparer.Equals(this, other);
/// <summary>
/// Whether this is equal to another object
/// </summary>
/// <param name="obj">The other object to compare</param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((Pixel) obj);
}
/// <summary>
/// Generates an integer for comparing this object
/// </summary>
/// <returns>The generated hash</returns>
public override int GetHashCode() => HashCode.Combine(BackColor, ForeColor, Content);
/// <summary>
/// Whether two pixels are equal
/// </summary>
/// <param name="a">First pixel to compare</param>
/// <param name="b">Second pixel to compare</param>
/// <returns>Whether they are equal</returns>
public static bool operator ==(Pixel a, Pixel b) => !ReferenceEquals(a, null) && a.Equals(b);
/// <summary>
/// Whether to pixels are not equal
/// </summary>
/// <param name="a">First pixel to compare</param>
/// <param name="b">Second pixel to compare</param>
/// <returns>Whether they are not equal</returns>
public static bool operator !=(Pixel a, Pixel b) => !(a == b);
/// <summary>
/// Returns the content of this pixel
/// </summary>
/// <returns>The content of this pixel</returns>
public override string ToString() => Content.ToString();
private sealed class ColorContentEqualityComparer : IEqualityComparer<Pixel>
{
public bool Equals(Pixel x, Pixel y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return x.GetHashCode().Equals(y.GetHashCode());
}
public int GetHashCode(Pixel obj) => obj.GetHashCode();
}
}
}

221
Commandline/TUI/Screen.cs Normal file
View File

@ -0,0 +1,221 @@
using System;
using System.Drawing;
using System.Linq;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Provides a front-end renderer for panels, draws using DiffDraw
/// </summary>
public class Screen : Panel
{
/// <summary>
/// Called if Escape is pressed, use this for flow control
/// </summary>
/// <param name="screen">This instance of the screen class</param>
/// <param name="e">Args</param>
public delegate void OnClose(Screen screen, EventArgs e);
/// <summary>
/// Called when the selected control is changed
/// </summary>
/// <param name="screen">This instance of the screen class</param>
/// <param name="args">Args</param>
public delegate void OnTabChanged(Screen screen, EventArgs args);
/// <summary>
/// Called by ReadInput if a change in the window size is detected. Use this for positioning
/// </summary>
/// <param name="screen">This instance of the screen class</param>
/// <param name="e">Args</param>
public delegate void OnWindowResize(Screen screen, EventArgs e);
private bool _color;
/// <summary>
/// Whether to output in color. Recommended for most terminals, might cause slowdowns in others
/// </summary>
public bool Color
{
get => _color;
set
{
if (_color != value)
{
_color = value;
DiffDraw.Draw(_color);
}
}
}
/// <summary>
/// The current index of the tab-selected control in an array of selectable controls
/// </summary>
public int TabPoint
{
get => _tabPoint;
set
{
if (_tabPoint != value)
{
_tabPoint = value;
}
}
}
private int _wndHeight = Console.WindowHeight;
private int _wndWidth = Console.WindowWidth;
private int _tabPoint;
/// <summary>
/// Creates a screen object. Multiple can be instantiated but drawing one overrides others. Use panels for that
/// </summary>
/// <param name="width">The screens with</param>
/// <param name="height">The screens height</param>
/// <param name="color">Whether to output in color</param>
public Screen(int width, int height, bool color = true)
{
Color = color;
Border = false;
Resize(width, height);
Tab();
}
/// <summary>
/// Resizes the screen. Make sure that this does not exceed the console size
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
public new void Resize(int width, int height)
{
Size = new Size(width, height);
DiffDraw.Clear(width, height);
}
/// <summary>
/// Renders the screen, draws it to the console and outputs the new state
/// </summary>
/// <returns>The new state of the screen</returns>
public new Pixel[,] Render()
{
FixSelection();
Pixel[,] tmp = base.Render();
DiffDraw.Clear(tmp);
DiffDraw.Draw(Color);
return tmp;
}
/// <summary>
/// Reads input from Console and calls according functions
/// </summary>
/// <param name="canRedraw">
/// Set to false to prevent redrawing if the screen should be updated. You can Render manually in
/// that case
/// </param>
public void ReadInput(bool canRedraw = true)
{
bool render = false;
while (Console.KeyAvailable)
{
Control[] controls = EnumerateRecursive();
Control[] selectable = controls.Where(s => s.Selectable).ToArray();
ConsoleKeyInfo input = Console.ReadKey();
switch (input.Key)
{
case ConsoleKey.Tab:
Tab(selectable, (input.Modifiers & ConsoleModifiers.Shift) == 0);
break;
case ConsoleKey.Enter:
if (selectable.Any() && selectable.Length >= TabPoint && selectable[TabPoint].Enabled)
selectable[TabPoint].InvokeClick(this);
break;
case ConsoleKey.Escape:
Close?.Invoke(this, new EventArgs());
break;
default:
if (selectable.Any() && selectable.Length >= TabPoint && selectable[TabPoint].Enabled)
selectable[TabPoint].InvokeInput(this, input);
InvokeInput(this, input);
break;
}
render = true;
}
if (_wndWidth != Console.WindowWidth || _wndHeight != Console.WindowHeight)
{
render = true;
_wndWidth = Console.WindowWidth;
_wndHeight = Console.WindowHeight;
WindowResize?.Invoke(this, new EventArgs());
}
if (canRedraw && render)
Render();
else
FixSelection();
}
/// <summary>
/// Increases the TabPoint or reverts back to 0 if at the end of selectables
/// </summary>
/// <param name="positive">Set to false to decrease instead</param>
public void Tab(bool positive = true)
{
Control[] controls = EnumerateRecursive();
Control[] selectable = controls.Where(s => s.Selectable).ToArray();
Tab(selectable, positive);
}
/// <summary>
/// Increases the TabPoint or reverts back to 0 if at the end of selectables
/// </summary>
/// <param name="selectable">The array of selectable controls to select from. You should most likely not use this</param>
/// <param name="positive">Set to false to decrease instead</param>
public void Tab(Control[] selectable, bool positive)
{
if (selectable.Any())
{
if (positive)
{
TabPoint++;
if (TabPoint >= selectable.Length) TabPoint = 0;
}
else
{
TabPoint--;
if (TabPoint < 0) TabPoint = selectable.Length - 1;
}
FixSelection(true);
}
}
private void FixSelection(bool draw = false)
{
Control[] controls = EnumerateRecursive();
Control[] selectable = controls.Where(s => s.Selectable).ToArray();
if (selectable.Any())
{
foreach (Control control in selectable) control.Selected = false;
selectable[TabPoint].Selected = true;
TabChanged?.Invoke(this, new EventArgs());
if (draw)
Render();
}
}
/// <summary>
/// Called if Escape is pressed, use this for flow control
/// </summary>
public event OnClose Close;
/// <summary>
/// Called by ReadInput if a change in the window size is detected. Use this for positioning
/// </summary>
public event OnWindowResize WindowResize;
/// <summary>
/// Called when the selected control is changed
/// </summary>
public event OnTabChanged TabChanged;
}
}

125
Commandline/TUI/Slider.cs Normal file
View File

@ -0,0 +1,125 @@
using System;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Provides a control to select a number from a range of numbers
/// </summary>
public class Slider : Control
{
private int _maxValue = 10;
private int _minValue;
private int _value = 5;
/// <summary>
/// The size of steps in this slider
/// </summary>
public int StepSize = 1;
/// <summary>
/// Generates a new slider
/// </summary>
public Slider()
{
Input += (screen, args) =>
{
switch (args.Info.Key)
{
case ConsoleKey.LeftArrow:
_value -= StepSize;
if (_value < MinValue)
_value = MinValue;
Value = _value;
ValueChanged?.Invoke(screen, new EventArgs());
break;
case ConsoleKey.RightArrow:
_value += StepSize;
if (_value > MaxValue)
_value = MaxValue;
Value = _value;
ValueChanged?.Invoke(screen, new EventArgs());
break;
}
};
}
/// <summary>
/// The maximum value for this slider
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">Thrown if too low/high</exception>
public int MaxValue
{
get => _maxValue;
set
{
if (value >= MinValue && value >= Value)
_maxValue = value;
else
throw new ArgumentOutOfRangeException(
"MaxValue must be larger than MinValue and equal to or larger than Value");
}
}
/// <summary>
/// The minimal value for this slider
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">Thrown if too low/high</exception>
public int MinValue
{
get => _minValue;
set
{
if (value <= MaxValue && value <= Value)
_minValue = value;
else
throw new ArgumentOutOfRangeException(
"MaxValue must be larger than MinValue and equal to or smaller than Value");
}
}
/// <summary>
/// The current value of this slider
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">Thrown if too low/high</exception>
public int Value
{
get => _value;
set
{
if (value <= MaxValue && value >= MinValue)
_value = value;
else
throw new ArgumentOutOfRangeException("Value must be between MinValue and MaxValue");
}
}
/// <inheritdoc />
public override bool Selectable { get; } = true;
/// <inheritdoc />
public override Pixel[,] Render()
{
int delta = MaxValue - MinValue;
int litValLen = Math.Max(MaxValue.ToString().Length, MinValue.ToString().Length);
int prevpts = Math.Max((Value - MinValue) * Size.Width / Math.Max(delta, 1) - litValLen - 2, 0);
int postpts = Math.Max(Size.Width - prevpts - litValLen - 2, 0);
char[,] rend = $"{new string('=', prevpts)}[{Value.ToString($"D{(Value < 0 ? litValLen - 1 : litValLen)}")}]{new string('=', postpts)}"
.ToNdArray2D();
int f1 = rend.GetLength(0);
int f2 = rend.GetLength(1);
Pixel[,] output = new Pixel[f1, f2];
output.Populate(new Pixel());
for (int i = 0; i < f1; i++)
for (int j = 0; j < f2; j++)
output[i, j] = new Pixel(Selected ? ForeColor : BackColor, Selected ? BackColor : ForeColor,
rend[i, j]);
return output;
}
/// <summary>
/// Called if the selected value of the slider changes
/// </summary>
public event OnClick ValueChanged;
}
}

180
Commandline/TUI/TextBox.cs Normal file
View File

@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using CC_Functions.Core;
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// A basic non-scrolling text-editor control
/// </summary>
public class TextBox : Control
{
/// <summary>
/// The text inside this textbox
/// </summary>
public string Content;
/// <summary>
/// The "Cursors" position in this text box
/// </summary>
public Point Cursor = new Point(0, 0);
/// <summary>
/// Creates a new text box
/// </summary>
/// <param name="content">The text inside this text box</param>
public TextBox(string content)
{
Content = content;
Input += (screen, args) => { ProcessInput(args.Info.Key, args.Info); };
Click += (screen, args) => ProcessInput(ConsoleKey.Enter, new ConsoleKeyInfo());
}
private string[] Lines
{
get => Content.Split('\n');
set => Content = string.Join('\n', value);
}
/// <inheritdoc />
public override bool Selectable { get; } = true;
/// <summary>
/// Function to process input
/// </summary>
/// <param name="key">The pressed key</param>
/// <param name="info">Input metadata</param>
private void ProcessInput(ConsoleKey key, ConsoleKeyInfo info)
{
string[] lines = Lines;
List<string> tmp;
int tmplen;
switch (key)
{
case ConsoleKey.LeftArrow:
Cursor.X--;
if (Cursor.X < 0)
{
if (Cursor.Y > 0) Cursor.Y--;
ProcessInput(ConsoleKey.End, info);
}
break;
case ConsoleKey.RightArrow:
Cursor.X++;
if (Cursor.X >= Lines[Cursor.Y].Length)
{
Cursor.Y++;
Cursor.X = 0;
if (Cursor.Y >= Lines.Length)
{
Cursor.Y--;
ProcessInput(ConsoleKey.End, info);
}
}
break;
case ConsoleKey.UpArrow:
if (Cursor.Y > 0)
{
Cursor.Y--;
if (Cursor.X >= Lines[Cursor.Y].Length) ProcessInput(ConsoleKey.End, info);
}
else
Cursor.X = 0;
break;
case ConsoleKey.DownArrow:
if (Cursor.Y < Lines.Length - 1)
{
Cursor.Y++;
if (Cursor.X >= Lines[Cursor.Y].Length) ProcessInput(ConsoleKey.End, info);
}
else
ProcessInput(ConsoleKey.End, info);
break;
case ConsoleKey.Home:
Cursor.X = 0;
break;
case ConsoleKey.End:
Cursor.X = Math.Max(Lines[Cursor.Y].Length - 1, 0);
break;
case ConsoleKey.PageUp:
for (int i = 0; i < 5; i++)
ProcessInput(ConsoleKey.UpArrow, info);
break;
case ConsoleKey.PageDown:
for (int i = 0; i < 5; i++)
ProcessInput(ConsoleKey.DownArrow, info);
break;
case ConsoleKey.Delete:
if (lines[Cursor.Y].Length > Cursor.X)
lines[Cursor.Y] = lines[Cursor.Y].Remove(Cursor.X, 1);
Lines = lines;
break;
case ConsoleKey.Backspace:
if (Cursor.X > 0 && lines[Cursor.Y].Length > 0)
{
lines[Cursor.Y] = lines[Cursor.Y].Remove(Cursor.X - 1, 1);
ProcessInput(ConsoleKey.LeftArrow, info);
}
else
{
if (Cursor.Y > 0)
{
tmp = lines.ToList();
tmplen = tmp[Cursor.Y - 1].Length;
tmp[Cursor.Y - 1] += tmp[Cursor.Y];
tmp.RemoveAt(Cursor.Y);
lines = tmp.ToArray();
Cursor.Y--;
Cursor.X = tmplen;
}
}
Lines = lines;
break;
case ConsoleKey.Enter:
if (lines.Length < Size.Height)
{
lines[Cursor.Y] = lines[Cursor.Y].Insert(Math.Max(Cursor.X, 0), "\n");
Cursor.Y++;
Cursor.X = 0;
Lines = lines;
}
break;
default:
if (lines[Cursor.Y].Length < Size.Width)
{
lines[Cursor.Y] = lines[Cursor.Y].Insert(Cursor.X, info.KeyChar.ToString());
Cursor.X++;
Lines = lines;
}
break;
}
}
/// <inheritdoc />
public override Pixel[,] Render()
{
char[,] inp1 = Content.ToNdArray2D();
inp1 = inp1.Resize(Size.Height, Size.Width - 2, SpecialChars.Empty);
char[,] inp = new char[Size.Width, Size.Height];
inp.Populate(SpecialChars.Empty);
for (int i = 0; i < Size.Height; i++)
{
inp[0, i] = '[';
inp[Size.Width - 1, i] = ']';
}
if (Lines.Length < Size.Width)
for (int i = 0; i < Size.Width; i++) inp[i, Size.Height - 1] = '.';
inp1.Rotate().CopyTo(inp, new Point(0, 1));
if (Selected)
inp[Math.Max(Cursor.X + 1, 1), Cursor.Y] = '▒';
Pixel[,] output = new Pixel[Size.Height, Size.Width];
output.Populate(new Pixel(Selected ? ForeColor : BackColor, Selected ? BackColor : ForeColor, SpecialChars.Empty));
for (int x = 0; x < Size.Width; x++)
for (int y = 0; y < Size.Height; y++)
output[y, x] = new Pixel(Selected ? ForeColor : BackColor, Selected ? BackColor : ForeColor, inp[x, y]);
return output;
}
}
}

136
Commandline/TableParser.cs Normal file
View File

@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace CC_Functions.Commandline
{
/// <summary>
/// Provides functions for parsing enumerables to powershell-like tables
/// </summary>
public static class TableParser
{
/// <summary>
/// Parses the enumerable to a table using with the specified headers and transformed to strings with the specified
/// selector
/// </summary>
/// <param name="values">The values to display</param>
/// <param name="columnHeaders">The headers for columns</param>
/// <param name="valueSelectors">Functions to get data for the cells</param>
/// <typeparam name="T">The type of the elements in the enumerable</typeparam>
/// <returns>The generated table</returns>
public static string ToStringTable<T>(this IEnumerable<T> values, string[] columnHeaders,
params Func<T, object>[] valueSelectors) => ToStringTable(values.ToArray(), columnHeaders, valueSelectors);
/// <summary>
/// Parses the array to a table using with the specified headers and transformed to strings with the specified selector
/// </summary>
/// <param name="values">The values to display</param>
/// <param name="columnHeaders">The headers for columns</param>
/// <param name="valueSelectors">Functions to get data for the cells</param>
/// <typeparam name="T">The type of the elements in the array</typeparam>
/// <returns>The generated table</returns>
public static string ToStringTable<T>(this T[] values, string[] columnHeaders,
params Func<T, object>[] valueSelectors)
{
Debug.Assert(columnHeaders.Length == valueSelectors.Length);
string[,] arrValues = new string[values.Length + 1, valueSelectors.Length];
// Fill headers
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
arrValues[0, colIndex] = columnHeaders[colIndex];
// Fill table rows
for (int rowIndex = 1; rowIndex < arrValues.GetLength(0); rowIndex++)
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
{
object value = valueSelectors[colIndex].Invoke(values[rowIndex - 1]);
arrValues[rowIndex, colIndex] = value != null ? value.ToString() : "null";
}
return ToStringTable(arrValues);
}
/// <summary>
/// Parses the array to a table
/// </summary>
/// <param name="arrValues">The cells of the table</param>
/// <returns>The generated table</returns>
public static string ToStringTable(this string[,] arrValues)
{
int[] maxColumnsWidth = GetMaxColumnsWidth(arrValues);
string headerSpliter = new string('-', maxColumnsWidth.Sum(i => i + 3) - 1);
StringBuilder sb = new StringBuilder();
for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++)
{
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
{
// Print cell
string cell = arrValues[rowIndex, colIndex];
cell = cell.PadRight(maxColumnsWidth[colIndex]);
sb.Append(" | ");
sb.Append(cell);
}
// Print end of line
sb.Append(" | ");
sb.AppendLine();
// Print splitter
if (rowIndex == 0)
{
sb.AppendFormat(" |{0}| ", headerSpliter);
sb.AppendLine();
}
}
return sb.ToString();
}
private static int[] GetMaxColumnsWidth(string[,] arrValues)
{
int[] maxColumnsWidth = new int[arrValues.GetLength(1)];
for (int colIndex = 0; colIndex < arrValues.GetLength(1); colIndex++)
for (int rowIndex = 0; rowIndex < arrValues.GetLength(0); rowIndex++)
{
int newLength = arrValues[rowIndex, colIndex].Length;
int oldLength = maxColumnsWidth[colIndex];
if (newLength > oldLength) maxColumnsWidth[colIndex] = newLength;
}
return maxColumnsWidth;
}
/// <summary>
/// Parses the enumerable to a table, transformed to strings with the specified selector
/// </summary>
/// <param name="values">The values to display</param>
/// <param name="valueSelectors">Functions to get data for the cells</param>
/// <typeparam name="T">The type of the elements in the enumerable</typeparam>
/// <returns>The generated table</returns>
public static string ToStringTable<T>(this IEnumerable<T> values,
params Expression<Func<T, object>>[] valueSelectors)
{
string[] headers = valueSelectors.Select(func => GetProperty(func).Name).ToArray();
Func<T, object>[] selectors = valueSelectors.Select(exp => exp.Compile()).ToArray();
return ToStringTable(values, headers, selectors);
}
private static PropertyInfo GetProperty<T>(Expression<Func<T, object>> expresstion)
{
if (expresstion.Body is UnaryExpression expression)
if (expression.Operand is MemberExpression memberExpression)
return memberExpression.Member as PropertyInfo;
if (expresstion.Body is MemberExpression body) return body.Member as PropertyInfo;
return null;
}
}
}

134
Core/ArrayFormatter.cs Normal file
View File

@ -0,0 +1,134 @@
using System;
using System.Drawing;
using System.Linq;
namespace CC_Functions.Core
{
/// <summary>
/// Contains extension functions to work with 1D and 2D arrays
/// </summary>
public static class ArrayFormatter
{
/// <summary>
/// Copies and resizes the array
/// </summary>
/// <param name="original">The original array. This is not modified</param>
/// <param name="elements">The new amount of elements</param>
/// <typeparam name="T">The type of elements in the array</typeparam>
/// <returns>The new, resized array</returns>
public static T[] Resize<T>(this T[] original, int elements)
{
T[] output = new T[original.Length];
original.CopyTo(output, 0);
Array.Resize(ref output, elements);
return output;
}
/// <summary>
/// Copies and resizes the array
/// </summary>
/// <param name="original">The original array. This is not modified</param>
/// <param name="rows">The new amount of elements in dimension 0</param>
/// <param name="cols">The new amount of elements in dimension 1</param>
/// <param name="defaultEl">The element to place in empty fields of the new array</param>
/// <typeparam name="T">The type of elements in the array</typeparam>
/// <returns>The new, resized array</returns>
public static T[,] Resize<T>(this T[,] original, int rows, int cols, T defaultEl = default)
{
T[,] newArray = new T[rows, cols];
newArray.Populate(defaultEl);
int minRows = Math.Min(rows, original.GetLength(0));
int minCols = Math.Min(cols, original.GetLength(1));
for (int i = 0; i < minRows; i++)
for (int j = 0; j < minCols; j++)
newArray[i, j] = original[i, j];
return newArray;
}
/// <summary>
/// Converts a string to a 2d char array using newlines
/// </summary>
/// <param name="source">The source string</param>
/// <param name="defaultEl">The element to place in empty fields of the new array</param>
/// <returns>The generated array</returns>
public static char[,] ToNdArray2D(this string source, char defaultEl = SpecialChars.Empty)
{
string[] sourceArr = source.Split('\n');
int width = sourceArr.Select(s => s.Length).OrderBy(s => s).Last();
int height = sourceArr.Length;
char[,] output = new char[height, width];
output.Populate(defaultEl);
for (int i = 0; i < sourceArr.Length; i++)
{
string s = sourceArr[i];
for (int j = 0; j < s.Length; j++)
output[i, j] = s[j];
}
return output;
}
/// <summary>
/// Clears and fills the array with the specified value
/// </summary>
/// <param name="arr">The array to populate</param>
/// <param name="value">The value to copy to the array, defaults to the default value (usually null)</param>
/// <typeparam name="T">The type of elements in the array</typeparam>
public static void Populate<T>(this T[] arr, T value = default)
{
for (int i = 0; i < arr.Length; i++) arr[i] = value;
}
/// <summary>
/// Clears and fills the array with the specified value
/// </summary>
/// <param name="arr">The array to populate</param>
/// <param name="value">The value to copy to the array, defaults to the default value (usually null)</param>
/// <typeparam name="T">The type of elements in the array</typeparam>
public static void Populate<T>(this T[,] arr, T value)
{
int w = arr.GetLength(0);
int h = arr.GetLength(1);
for (int i = 0; i < w; i++)
for (int j = 0; j < h; j++)
arr[i, j] = value;
}
/// <summary>
/// Copies the content of a 2D array to another with offset
/// </summary>
/// <param name="arr">The array to copy from</param>
/// <param name="target">The array to copy to</param>
/// <param name="offset">The copy offset</param>
/// <typeparam name="T">The type of elements in the array</typeparam>
public static void CopyTo<T>(this T[,] arr, T[,] target, Point offset)
{
int w = arr.GetLength(1);
int h = arr.GetLength(0);
int mw = target.GetLength(1);
int mh = target.GetLength(0);
int ow = offset.X;
int oh = offset.Y;
if (oh >= 0 && ow >= 0 && mw >= 0 && mh >= 0 && w >= 0 && h >= 0)
for (int x = ow; x < Math.Min(mw, w + ow); x++)
for (int y = oh; y < Math.Min(mh, h + oh); y++)
target[y, x] = arr[y - oh, x - ow];
}
/// <summary>
/// Copies and rotates the 2d array (row->column, column->row)
/// </summary>
/// <param name="arr">The array to copy from</param>
/// <typeparam name="T">The type of elements in the array</typeparam>
/// <returns>The new, rotated array</returns>
public static T[,] Rotate<T>(this T[,] arr)
{
int w = arr.GetLength(0);
int h = arr.GetLength(1);
T[,] target = new T[h, w];
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
target[y, x] = arr[x, y];
return target;
}
}
}

28
Core/Core.csproj Normal file
View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>CC_Functions.Core</RootNamespace>
<AssemblyName>CC_Functions.Core</AssemblyName>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Core</PackageId>
<Title>CC-Functions.Core</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code without external dependencies. Used in other CC_Functions packages</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Core.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DocumentationFile>bin\Release\Core.xml</DocumentationFile>
</PropertyGroup>
</Project>

255
Core/GenericExtensions.cs Normal file
View File

@ -0,0 +1,255 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Threading;
namespace CC_Functions.Core
{
/// <summary>
/// Extension methods for various types
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Gets an element from the dictionary or adds the default
/// </summary>
/// <param name="dict">The dictionary to get from</param>
/// <param name="key">The key to check</param>
/// <param name="def">The default value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The element at the key</returns>
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue def = default)
{
if (!dict.ContainsKey(key))
dict[key] = def;
return dict[key];
}
/// <summary>
/// Sets an element and returns it
/// </summary>
/// <param name="dict">The dictionary to set in</param>
/// <param name="key">The key to set at</param>
/// <param name="val">The value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The value that was placed</returns>
public static TValue Set<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue val = default)
{
dict[key] = val;
return dict[key];
}
/// <summary>
/// Tries to cast an object
/// </summary>
/// <param name="o">The object to try to parse</param>
/// <param name="parsed">The parsed object (if successful) or the default (usually null)</param>
/// <typeparam name="T">The type to cast to</typeparam>
/// <returns>Whether the cast was successful</returns>
public static bool TryCast<T>(this object o, out T parsed)
{
try
{
parsed = (T) o;
return true;
}
catch
{
parsed = default;
return false;
}
}
/// <summary>
/// Runs a function that transforms an object in-line
/// </summary>
/// <param name="self">The object to run on</param>
/// <param name="func">The function to run</param>
/// <typeparam name="TIn">The input type</typeparam>
/// <typeparam name="TOut">The output type</typeparam>
/// <returns></returns>
public static TOut SelectO<TIn, TOut>(this TIn self, Func<TIn, TOut> func) => func.Invoke(self);
/// <summary>
/// Runs a function under a condition in-line (equal to if)
/// </summary>
/// <param name="condition">The condition to check</param>
/// <param name="func">The function to run</param>
public static void RunIf(bool condition, Action func)
{
if (condition)
func();
}
/// <summary>
/// Parses a string to a value of an enum
/// </summary>
/// <param name="value">The string to parse</param>
/// <typeparam name="TEnum">The enum type (MUST be an enum)</typeparam>
/// <returns>The element</returns>
public static TEnum ParseToEnum<TEnum>(string value) => (TEnum) Enum.Parse(typeof(TEnum),
Enum.GetNames(typeof(TEnum)).First(s => s.ToLower() == value.ToLower()));
/// <summary>
/// Parses a string to a nullable bool (defaults to null if parse fails)
/// </summary>
/// <param name="value">The st string to parse</param>
/// <returns>The output nullable bool</returns>
public static bool? ParseBool(string value) =>
bool.TryParse(value, out bool tmp) ? (bool?) tmp : null;
/// <summary>
/// AND operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool And(this bool? left, bool? right) => left.True() && right.True();
/// <summary>
/// OR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Or(this bool? left, bool? right) => left.True() || right.True();
/// <summary>
/// XOR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Xor(this bool? left, bool? right) => left.Or(right) && !left.And(right);
/// <summary>
/// Whether the nullable bool is true (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is true</returns>
public static bool True(this bool? self) => self == true;
/// <summary>
/// Whether the nullable bool is false (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is false</returns>
public static bool False(this bool? self) => self == false;
/// <summary>
/// Whether the nullable bool is null
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is null</returns>
public static bool Null(this bool? self) => self == null;
/// <summary>
/// Removes an element from a dictionary by its index (not key)
/// </summary>
/// <param name="dict">The dictionary to remove from</param>
/// <param name="index">The index of the value</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public static void RemoveAt<TKey, TValue>(this Dictionary<TKey, TValue> dict, int index) =>
dict.Remove(dict.Keys.ToArray()[index]);
/// <summary>
/// "Unshorten" (follow) an URL
/// </summary>
/// <param name="self">The URL to unshorten</param>
/// <returns>The unshortened URL</returns>
public static Uri Unshorten(this Uri self)
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(self);
req.AllowAutoRedirect = true;
req.MaximumAutomaticRedirections = 100;
WebResponse resp = req.GetResponse();
return resp.ResponseUri;
}
/// <summary>
/// Rounds a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to round</param>
/// <returns>The rounded Rectangle</returns>
public static Rectangle Round(this RectangleF self) => Rectangle.Round(self);
/// <summary>
/// Ceilings a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to ceil (?)</param>
/// <returns>The ceiled (?) Rectangle</returns>
public static Rectangle Ceiling(this RectangleF self) => Rectangle.Ceiling(self);
/// <summary>
/// Pings an URL to check for availability
/// </summary>
/// <param name="self">The URL to check</param>
/// <returns>Whether the service is online</returns>
public static bool Ping(this Uri self)
{
try
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(self);
request.Timeout = 3000;
request.AllowAutoRedirect = true;
using WebResponse response = request.GetResponse();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Gets the size of a dictionary
/// </summary>
/// <param name="directory">The dictionary to check</param>
/// <returns>The size of the dictionary</returns>
public static long GetSize(this DirectoryInfo directory) => IO.GetDirectorySize(directory.FullName);
/// <summary>
/// Adds a directory to an archive recursively
/// </summary>
/// <param name="archive">The archive to add to</param>
/// <param name="folderPath">The directory to add</param>
/// <param name="entryName">The name of the directory in-archive</param>
/// <param name="ignoredExtensions">Extensions for files to ignore</param>
/// <param name="ignoredPaths">Paths to exclude from adding</param>
/// <returns>The new entry</returns>
public static ZipArchiveEntry AddDirectory(this ZipArchive archive, string folderPath, string entryName,
string[] ignoredExtensions, string[] ignoredPaths)
{
entryName = entryName.TrimEnd('/');
ZipArchiveEntry result = archive.CreateEntry($"{entryName}/");
string[] files = Directory.GetFiles(folderPath);
foreach (string t in files)
if (!ignoredExtensions.Contains(Path.GetExtension(t)) &&
!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.CreateEntryFromFile(t, $"{entryName}/{Path.GetFileName(t)}");
string[] dirs = Directory.GetDirectories(folderPath);
foreach (string t in dirs)
if (!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.AddDirectory(t, $"{entryName}/{Path.GetFileName(t)}", ignoredExtensions,
ignoredPaths);
return result;
}
/// <summary>
/// Sets the threads cultureInfo properties to InvariantCulture. For testing
/// </summary>
/// <param name="thread">The thread to modify</param>
public static void ForceInvariantCulture(this Thread thread)
{
thread.CurrentCulture = CultureInfo.InvariantCulture;
thread.CurrentUICulture = CultureInfo.InvariantCulture;
}
}
}

35
Core/IO.cs Normal file
View File

@ -0,0 +1,35 @@
using System;
using System.IO;
namespace CC_Functions.Core
{
/// <summary>
/// IO functions
/// </summary>
public static class IO
{
/// <summary>
/// Recursively gets the size of an directory
/// </summary>
/// <param name="path">The path of the directory</param>
/// <returns>The size of the directory</returns>
public static long GetDirectorySize(string path)
{
string[] a = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
long size = 0;
foreach (string t in a)
size += new FileInfo(t).Length;
return size;
}
/// <summary>
/// Check whether the paths are equivalent (ignores case)
/// </summary>
/// <param name="path1">The first path to check</param>
/// <param name="path2">The second path to check</param>
/// <returns>Whether the paths are equal</returns>
public static bool CheckPathEqual(string path1, string path2) =>
Path.GetFullPath(path1)
.Equals(Path.GetFullPath(path2), StringComparison.InvariantCultureIgnoreCase);
}
}

156
Core/SpecialChars.cs Normal file
View File

@ -0,0 +1,156 @@
namespace CC_Functions.Core
{
/// <summary>
/// Characters for use in CC-Functions.CommandLine
/// </summary>
public static class SpecialChars
{
/// <summary>
/// The space character
/// </summary>
public const char Empty = ' ';
/// <summary>
/// Wall with two lines
/// </summary>
public static class TwoLineSimple
{
// 1 connectors
/// <summary>
/// Wall with specified points
/// </summary>
public const char Up = '║';
/// <summary>
/// Wall with specified points
/// </summary>
public const char Down = '║';
/// <summary>
/// Wall with specified points
/// </summary>
public const char Left = '═';
/// <summary>
/// Wall with specified points
/// </summary>
public const char Right = '═';
// 2 connectors
/// <summary>
/// Wall with specified points
/// </summary>
public const char UpDown = '║';
/// <summary>
/// Wall with specified points
/// </summary>
public const char LeftRight = '═';
/// <summary>
/// Wall with specified points
/// </summary>
public const char DownRight = '╔';
/// <summary>
/// Wall with specified points
/// </summary>
public const char UpRight = '╚';
/// <summary>
/// Wall with specified points
/// </summary>
public const char DownLeft = '╗';
/// <summary>
/// Wall with specified points
/// </summary>
public const char UpLeft = '╝';
// 3 connectors
/// <summary>
/// Wall with specified points
/// </summary>
public const char UpDownLeft = '╣';
/// <summary>
/// Wall with specified points
/// </summary>
public const char UpDownRight = '╠';
/// <summary>
/// Wall with specified points
/// </summary>
public const char UpLeftRight = '╩';
/// <summary>
/// Wall with specified points
/// </summary>
public const char DownLeftRight = '╦';
// 4 connectors
/// <summary>
/// Wall with specified points
/// </summary>
public const char UpDownLeftRight = '╬';
}
/// <summary>
/// Simple line
/// </summary>
public static class OneLineSimple
{
// 1 connectors
/// <summary>
/// Line with specified points
/// </summary>
public const char Up = '╵';
/// <summary>
/// Line with specified points
/// </summary>
public const char Down = '╷';
/// <summary>
/// Line with specified points
/// </summary>
public const char Left = '╴';
/// <summary>
/// Line with specified points
/// </summary>
public const char Right = '╶';
// 2 connectors
public const char UpDown = '│';
/// <summary>
/// Line with specified points
/// </summary>
public const char LeftRight = '─';
/// <summary>
/// Line with specified points
/// </summary>
public const char DownRight = '┌';
/// <summary>
/// Line with specified points
/// </summary>
public const char UpRight = '└';
/// <summary>
/// Line with specified points
/// </summary>
public const char DownLeft = '┐';
/// <summary>
/// Line with specified points
/// </summary>
public const char UpLeft = '┘';
// 3 connectors
/// <summary>
/// Line with specified points
/// </summary>
public const char UpDownLeft = '┤';
/// <summary>
/// Line with specified points
/// </summary>
public const char UpDownRight = '├';
/// <summary>
/// Line with specified points
/// </summary>
public const char UpLeftRight = '┴';
/// <summary>
/// Line with specified points
/// </summary>
public const char DownLeftRight = '┬';
// 4 connectors
/// <summary>
/// Line with specified points
/// </summary>
public const char UpDownLeftRight = '┼';
}
}
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 J. Fronny
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CC_Functions.Misc
{
public static class ArrayFormatter
{
public static string ArrayToString(object[] Input, string Seperator = "\r\n")
{
try
{
string a = "";
for (int i = 0; i < Input.Length; i++)
a += Input[i].ToString() + Seperator;
return a.Remove(a.Length - 1 - Seperator.Length);
}
catch { throw; }
}
}
}

98
Misc/Crypto.cs Normal file
View File

@ -0,0 +1,98 @@
using System;
using System.IO;
using System.Security.Cryptography;
namespace CC_Functions.Misc
{
/// <summary>
/// Contains cryptographic functions
/// </summary>
public static class Crypto
{
/// <summary>
/// Encrypts an array of bytes using SHA512. Use with <see cref="Decrypt">Decrypt</see>
/// </summary>
/// <param name="data">The array of bytes to encrypt</param>
/// <param name="key">The key for encryption, later required to decrypt</param>
/// <returns>The encrypted data</returns>
/// <exception cref="ArgumentException">Thrown if provided data is invalid</exception>
public static byte[] Encrypt(byte[] data, byte[] key)
{
if (key is null)
throw new ArgumentException("Key must have valid value.", nameof(key));
if (data is null)
throw new ArgumentException("The text must have valid value.", nameof(data));
byte[] buffer = data;
SHA512CryptoServiceProvider hash = new SHA512CryptoServiceProvider();
byte[] aesKey = new byte[24];
Buffer.BlockCopy(hash.ComputeHash(key), 0, aesKey, 0, 24);
using Aes aes = Aes.Create();
if (aes == null)
throw new ArgumentException("Parameter must not be null.", nameof(aes));
aes.Key = aesKey;
using ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using MemoryStream resultStream = new MemoryStream();
using (CryptoStream aesStream = new CryptoStream(resultStream, encryptor, CryptoStreamMode.Write))
{
using MemoryStream plainStream = new MemoryStream(buffer);
plainStream.CopyTo(aesStream);
}
byte[] result = resultStream.ToArray();
byte[] combined = new byte[aes.IV.Length + result.Length];
Array.ConstrainedCopy(aes.IV, 0, combined, 0, aes.IV.Length);
Array.ConstrainedCopy(result, 0, combined, aes.IV.Length, result.Length);
return combined;
}
/// <summary>
/// Decrypts an SHA512-encrypted byte array. Use with <see cref="Encrypt">Encrypt</see>
/// </summary>
/// <param name="encrypted">The array of bytes to decrypt</param>
/// <param name="key">The key the data was encrypted with</param>
/// <returns>The decrypted data</returns>
/// <exception cref="ArgumentException">Thrown if provided data is invalid</exception>
public static byte[] Decrypt(byte[] encrypted, byte[] key)
{
if (key is null)
throw new ArgumentException("Key must have valid value.", nameof(key));
if (encrypted is null)
throw new ArgumentException("The encrypted text must have valid value.", nameof(encrypted));
byte[] combined = encrypted;
byte[] buffer = new byte[combined.Length];
SHA512CryptoServiceProvider hash = new SHA512CryptoServiceProvider();
byte[] aesKey = new byte[24];
Buffer.BlockCopy(hash.ComputeHash(key), 0, aesKey, 0, 24);
using Aes aes = Aes.Create();
if (aes == null)
throw new ArgumentException("Parameter must not be null.", nameof(aes));
aes.Key = aesKey;
byte[] iv = new byte[aes.IV.Length];
byte[] ciphertext = new byte[buffer.Length - iv.Length];
Array.ConstrainedCopy(combined, 0, iv, 0, iv.Length);
Array.ConstrainedCopy(combined, iv.Length, ciphertext, 0, ciphertext.Length);
aes.IV = iv;
using ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using MemoryStream resultStream = new MemoryStream();
using (CryptoStream aesStream = new CryptoStream(resultStream, decryptor, CryptoStreamMode.Write))
{
using MemoryStream plainStream = new MemoryStream(ciphertext);
plainStream.CopyTo(aesStream);
}
return resultStream.ToArray();
}
}
}

31
Misc/GenericExtensions.cs Normal file
View File

@ -0,0 +1,31 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using CC_Functions.Core;
namespace CC_Functions.Misc
{
/// <summary>
/// Extension methods for various types
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Extension method for <see cref="Crypto">Crypto's</see> Encrypt
/// </summary>
/// <param name="self">The data to encrypt</param>
/// <param name="key">The key to encrypt with</param>
/// <returns>The encrypted data</returns>
public static byte[] Encrypt(this byte[] self, byte[] key) => Crypto.Encrypt(self, key);
/// <summary>
/// Extension method for <see cref="Crypto">Crypto's</see> Decrypt
/// </summary>
/// <param name="self">The data to decrypt</param>
/// <param name="key">The key to decrypt with</param>
/// <returns>The decrypted data</returns>
public static byte[] Decrypt(this byte[] self, byte[] key) => Crypto.Decrypt(self, key);
}
}

124
Misc/HID.cs Normal file
View File

@ -0,0 +1,124 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Security.Cryptography;
using System.Text;
namespace CC_Functions.Misc
{
/// <summary>
/// Functions for hardware identidiers
/// </summary>
public static class Hid
{
/// <summary>
/// Whether to force Win32-based operation
/// </summary>
public static bool ForceWindows = false;
private static byte[] _fingerPrint;
private static readonly string HidClasses = @"Win32_Processor:UniqueId
Win32_Processor:ProcessorId
Win32_Processor:Name
Win32_Processor:Manufacturer
Win32_BIOS:Manufacturer
Win32_BIOS:SMBIOSBIOSVersion
Win32_BIOS:IdentificationCode
Win32_BIOS:SerialNumber
Win32_BIOS:ReleaseDate
Win32_BIOS:Version
Win32_BaseBoard:Model
Win32_BaseBoard:Manufacturer
Win32_BaseBoard:Name
Win32_BaseBoard:SerialNumber
Win32_NetworkAdapterConfiguration:MACAddress";
/// <summary>
/// The HID for this machine
/// </summary>
public static byte[] Value
{
get
{
if (_fingerPrint != null) return _fingerPrint;
string fingerprintTmp = "";
if (ForceWindows ||
new[]
{
PlatformID.Xbox, PlatformID.Win32S, PlatformID.Win32Windows, PlatformID.Win32NT,
PlatformID.WinCE
}.Contains(Environment.OSVersion.Platform))
HidClasses.Split(new[] {"\r\n"}, StringSplitOptions.None).Select(s =>
{
if (s.StartsWith("\n"))
s = s.Remove(0, 1);
return s.Split(':');
}).ToList().ForEach(s =>
{
using ManagementClass mc = new ManagementClass(s[0]);
using ManagementObjectCollection moc = mc.GetInstances();
ManagementBaseObject[] array = moc.OfType<ManagementBaseObject>().ToArray();
for (int j = 0; j < array.Length; j++)
try
{
fingerprintTmp += array[j][s[1]].ToString();
break;
}
catch
{
Console.WriteLine("Failed to read property");
}
});
else //Linux implementation. This will not work if you are using Mono on windows or do not have "uname", "lscpu" and "id" available
{
Process p = new Process
{
StartInfo =
{
UseShellExecute = false,
RedirectStandardOutput = true,
FileName = "uname",
Arguments = "-nmpio"
}
};
p.Start();
fingerprintTmp = p.StandardOutput.ReadToEnd();
p.WaitForExit();
p.StartInfo.FileName = "lscpu";
p.StartInfo.Arguments = "-ap";
p.Start();
fingerprintTmp += p.StandardOutput.ReadToEnd();
p.WaitForExit();
p.StartInfo.FileName = "ip";
p.StartInfo.Arguments = "link";
p.Start();
fingerprintTmp += p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
using MD5 sec = new MD5CryptoServiceProvider();
byte[] bt = Encoding.ASCII.GetBytes(fingerprintTmp);
_fingerPrint = sec.ComputeHash(bt);
return _fingerPrint;
}
}
/// <summary>
/// Encrypts data using <see cref="Crypto">Crypto's</see> Encrypt and the HID
/// </summary>
/// <param name="unencrypted">The data to encrypt</param>
/// <returns>The encrypted data</returns>
public static byte[] EncryptLocal(byte[] unencrypted) =>
Crypto.Encrypt(unencrypted, Value);
/// <summary>
/// Decrypts data using <see cref="Crypto">Crypto's</see> Decrypt and the HID
/// </summary>
/// <param name="encrypted">The data to decrypt</param>
/// <returns>The decrypted data</returns>
public static byte[] DecryptLocal(byte[] encrypted) =>
Crypto.Decrypt(encrypted, Value);
}
}

15
Misc/HIDClasses.txt Normal file
View File

@ -0,0 +1,15 @@
"Win32_Processor:UniqueId
Win32_Processor:ProcessorId
Win32_Processor:Name
Win32_Processor:Manufacturer
Win32_BIOS:Manufacturer
Win32_BIOS:SMBIOSBIOSVersion
Win32_BIOS:IdentificationCode
Win32_BIOS:SerialNumber
Win32_BIOS:ReleaseDate
Win32_BIOS:Version
Win32_BaseBoard:Model
Win32_BaseBoard:Manufacturer
Win32_BaseBoard:Name
Win32_BaseBoard:SerialNumber
Win32_NetworkAdapterConfiguration:MACAddress:IPEnabled"

67
Misc/MathEx.cs Normal file
View File

@ -0,0 +1,67 @@
using System;
namespace CC_Functions.Misc
{
public static class MathEx
{
public static decimal Abs(this decimal value) => Math.Abs(value);
public static double Abs(this double value) => Math.Abs(value);
public static float Abs(this float value) => Math.Abs(value);
public static int Abs(this int value) => Math.Abs(value);
public static long Abs(this long value) => Math.Abs(value);
public static sbyte Abs(this sbyte value) => Math.Abs(value);
public static short Abs(this short value) => Math.Abs(value);
public static double Acos(this double d) => Math.Acos(d);
public static double Asin(this double d) => Math.Asin(d);
public static double Atan(this double d) => Math.Atan(d);
public static double Atan2(this double x, double y) => Math.Atan2(x, y);
public static decimal Ceiling(this decimal d) => Math.Ceiling(d);
public static double Ceiling(this double d) => Math.Ceiling(d);
public static double Cos(this double d) => Math.Cos(d);
public static double Cosh(this double value) => Math.Cosh(value);
public static double Exp(this double d) => Math.Exp(d);
public static decimal Floor(this decimal d) => Math.Floor(d);
public static double Floor(this double d) => Math.Floor(d);
public static double Log(this double d) => Math.Log(d);
public static double Log(this double d, double newBase) => Math.Log(d, newBase);
public static double Log10(this double d) => Math.Log10(d);
//Max
//Min
public static double Pow(this double x, double y) => Math.Pow(x, y);
public static double Root(this double value, double n) => Math.Pow(value, 1 / n);
public static decimal Round(this decimal d) => Math.Round(d);
public static decimal Round(this decimal d, MidpointRounding mode) => Math.Round(d, mode);
public static decimal Round(this decimal d, int decimals) => Math.Round(d, decimals);
public static decimal Round(this decimal d, int decimals, MidpointRounding mode) =>
Math.Round(d, decimals, mode);
public static double Round(this double a) => Math.Round(a);
public static double Round(this double value, MidpointRounding mode) => Math.Round(value, mode);
public static double Round(this double value, int digits) => Math.Round(value, digits);
public static double Round(this double value, int digits, MidpointRounding mode) =>
Math.Round(value, digits, mode);
public static int Sign(this decimal value) => Math.Sign(value);
public static int Sign(this double value) => Math.Sign(value);
public static int Sign(this float value) => Math.Sign(value);
public static int Sign(this int value) => Math.Sign(value);
public static int Sign(this long value) => Math.Sign(value);
public static int Sign(this sbyte value) => Math.Sign(value);
public static int Sign(this short value) => Math.Sign(value);
public static double Sin(this double a) => Math.Sin(a);
public static double Sinh(this double value) => Math.Sinh(value);
public static double Sqrt(this double d) => Math.Sqrt(d);
public static double Tan(this double a) => Math.Tan(a);
public static double Tanh(this double value) => Math.Tanh(value);
public static decimal Truncate(this decimal d) => Math.Truncate(d);
public static double Truncate(this double d) => Math.Truncate(d);
public static long BigMul(this int a, int b) => Math.BigMul(a, b);
public static int DivRem(this int a, int b, out int result) => Math.DivRem(a, b, out result);
public static long DivRem(this int a, int b, out long result) => Math.DivRem(a, b, out result);
public static double IEEERemainder(this double x, double y) => Math.IEEERemainder(x, y);
}
}

View File

@ -1,50 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B80D5E09-B935-4602-A173-BAF7C1974999}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CC_Functions.Misc</RootNamespace>
<AssemblyName>CC_Functions.Misc</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<LangVersion>8</LangVersion>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Misc</PackageId>
<Title>CC-Functions.Misc</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code used across my projects. I do NOT recommend using this in your own project!</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Misc.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Misc.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<EmbeddedResource Include="HIDClasses.txt" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArrayFormatter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Security.cs" />
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
<ItemGroup>
<Reference Include="System.IO.Compression" Condition="'$(TargetFramework)' == 'net461'" />
<Reference Include="System.IO.Compression.FileSystem" Condition="'$(TargetFramework)' == 'net461'" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
</Project>

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Misc")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Misc")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b80d5e09-b935-4602-a173-baf7c1974999")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Misc
{
public static class MiscFunctions
{
public static bool IsAdministrator => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
public static long GetDirectorySize(string path)
{
try
{
string[] a = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
long size = 0;
for (int i = 0; i < a.Length; i++)
{
size += new FileInfo(a[i]).Length;
}
return size;
}
catch { throw; }
}
}
}

BIN
README.md

Binary file not shown.

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

View File

@ -1,210 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CC_Functions.W32;
using static CC_Functions.W32.Power;
namespace CC_Functions.W32.Test
{
public partial class Form1 : Form
{
MouseHook mHook;
KeyboardHook kHook;
public static Wnd32 tmpWnd;
public static Form1 mainF;
public static Form frm;
public static Label lab;
public Form1()
{
InitializeComponent();
mainF = this;
tmpWnd = Wnd32.fromForm(this);
#if DEBUG
tmpWnd.MakeOverlay();
#endif
set_up_box(power_mode_box, typeof(ShutdownMode));
set_up_box(power_reason_box, typeof(ShutdownReason));
set_up_box(power_mod_box, typeof(ShutdownMod));
mHook = new MouseHook();
kHook = new KeyboardHook();
wnd_action_pos_x_bar.Maximum = Screen.PrimaryScreen.Bounds.Width;
wnd_action_pos_y_bar.Maximum = Screen.PrimaryScreen.Bounds.Height;
wnd_action_pos_w_bar.Maximum = Screen.PrimaryScreen.Bounds.Width;
wnd_action_pos_h_bar.Maximum = Screen.PrimaryScreen.Bounds.Height;
}
public void set_up_box(ComboBox box, Type enumT)
{
box.DataSource = Enum.GetNames(enumT);
var tmp = Enum.GetValues(enumT);
box.Tag = new object[tmp.Length];
int i = 0;
foreach (object o in tmp)
{
((object[])box.Tag)[i] = o;
i++;
}
}
public object get_box_value(ComboBox box) => ((object[])box.Tag)[box.SelectedIndex];
private void Power_execute_Click(object sender, EventArgs e) => RaiseEvent((ShutdownMode)get_box_value(power_mode_box), (ShutdownReason)get_box_value(power_reason_box), (ShutdownMod)get_box_value(power_mod_box));
private void Wnd_select_self_Click(object sender, EventArgs e) => tmpWnd = Wnd32.fromForm(this);
private void Wnd_select_title_button_Click(object sender, EventArgs e) => tmpWnd = Wnd32.fromMetadata(null, wnd_select_title_box.Text);
private void Wnd_selet_class_button_Click(object sender, EventArgs e) => tmpWnd = Wnd32.fromMetadata(wnd_select_class_box.Text, null);
private void Wnd_action_title_set_Click(object sender, EventArgs e) => tmpWnd.title = wnd_select_title_box.Text;
private void Wnd_action_title_get_Click(object sender, EventArgs e)
{
wnd_select_title_box.Text = tmpWnd.title;
wnd_action_enabled.Enabled = tmpWnd.enabled;
wnd_select_selected.Text = "Selected: " + tmpWnd.hWnd.ToString();
try { wnd_action_pos_x_bar.Value = tmpWnd.position.X; } catch { }
try { wnd_action_pos_y_bar.Value = tmpWnd.position.Y; } catch { }
try { wnd_action_pos_w_bar.Value = tmpWnd.position.Width; } catch { }
try { wnd_action_pos_h_bar.Value = tmpWnd.position.Height; } catch { }
}
private void Wnd_action_enabled_CheckedChanged(object sender, EventArgs e) => tmpWnd.enabled = wnd_action_enabled.Enabled;
private void Wnd_action_front_Click(object sender, EventArgs e) => tmpWnd.isForeground = true;
private void Wnd_action_overlay_Click(object sender, EventArgs e) => tmpWnd.MakeOverlay();
private void Wnd_action_destroy_Click(object sender, EventArgs e) => tmpWnd.Destroy();
private void Wnd_select_mouse_Click(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
tmpWnd = Wnd32.fromForm(this);
tmpWnd.enabled = false;
frm = new Form();
frm.BackColor = Color.White;
frm.Opacity = 0.4f;
frm.FormBorderStyle = FormBorderStyle.None;
frm.WindowState = FormWindowState.Maximized;
frm.Click += Frm_Click;
frm.MouseMove += Frm_MouseMove;
lab = new Label();
frm.Controls.Add(lab);
frm.Show();
Wnd32.fromForm(frm).MakeOverlay();
}
private void Frm_Click(object sender, EventArgs e)
{
frm.Hide();
frm.WindowState = FormWindowState.Minimized;
Wnd32 tmp = Wnd32.fromPoint(MousePosition);
tmpWnd.enabled = true;
tmpWnd.isForeground = true;
tmpWnd = tmp;
mainF.WindowState = FormWindowState.Normal;
frm.Close();
}
private void Frm_MouseMove(object sender, MouseEventArgs e)
{
lab.Text = Wnd32.fromPoint(MousePosition).ToString();
lab.Location = new Point(Cursor.Position.X + 5, Cursor.Position.Y + 5);
}
private void Mouse_enabled_CheckedChanged(object sender, EventArgs e)
{
if (mouse_enabled.Checked)
{
mHook.OnMouse += MHook_OnMouse;
}
else
{
mHook.OnMouse -= MHook_OnMouse;
}
}
private void MHook_OnMouse(MouseHookEventArgs _args)
{
mouse_log.Text = _args.Message.ToString() + " -|- " + _args.Point.ToString() + "\r\n" + mouse_log.Text;
}
private void Mouse_log_TextChanged(object sender, EventArgs e)
{
if (mouse_log.Lines.Length > 10)
{
var tmp = mouse_log.Lines.ToList();
tmp.RemoveRange(9, mouse_log.Lines.Length - 9);
mouse_log.Lines = tmp.ToArray();
tmp = null;
}
}
private void Keyboard_enabled_CheckedChanged(object sender, EventArgs e)
{
if (keyboard_enabled.Checked)
{
kHook.OnKeyPress += KHook_OnKeyPress;
}
else
{
kHook.OnKeyPress -= KHook_OnKeyPress;
}
}
private void KHook_OnKeyPress(KeyboardHookEventArgs _args)
{
keyboard_log.Text = _args.Key.ToString() + "\r\n" + keyboard_log.Text;
}
private void Keyboard_log_TextChanged(object sender, EventArgs e)
{
if (keyboard_log.Lines.Length > 10)
{
var tmp = keyboard_log.Lines.ToList();
tmp.RemoveRange(9, keyboard_log.Lines.Length - 9);
keyboard_log.Lines = tmp.ToArray();
tmp = null;
}
}
private void Wnd_action_pos_Click(object sender, EventArgs e)
{
tmpWnd.position = new Rectangle(wnd_action_pos_x_bar.Value, wnd_action_pos_y_bar.Value, wnd_action_pos_w_bar.Value, wnd_action_pos_h_bar.Value);
}
private void Exit_Click(object sender, EventArgs e)
{
if ((DateTime.Now - mST).TotalSeconds < 0.15f)
Application.Exit();
}
bool moving;
Point locDelB;
DateTime mST;
private void Exit_MouseMove(object sender, MouseEventArgs e)
{
if (moving && (DateTime.Now - mST).TotalSeconds >= 0.1f)
Location = new Point(locDelB.X + Cursor.Position.X, locDelB.Y + Cursor.Position.Y);
}
private void Exit_MouseDown(object sender, MouseEventArgs e)
{
mST = DateTime.Now;
locDelB = new Point(Location.X - Cursor.Position.X, Location.Y - Cursor.Position.Y);
moving = true;
}
private void Exit_MouseUp(object sender, MouseEventArgs e)
{
moving = false;
}
}
}

View File

@ -1,6 +1,6 @@
namespace CC_Functions.W32.Test
{
partial class Form1
partial class MainForm
{
/// <summary>
/// Required designer variable.
@ -28,7 +28,7 @@
/// </summary>
private void InitializeComponent()
{
this.exit = new System.Windows.Forms.Button();
this.components = new System.ComponentModel.Container();
this.keyboard_log = new System.Windows.Forms.TextBox();
this.keyboard = new System.Windows.Forms.GroupBox();
this.keyboard_enabled = new System.Windows.Forms.CheckBox();
@ -54,18 +54,39 @@
this.power_mode_box = new System.Windows.Forms.ComboBox();
this.wnd_select_mouse = new System.Windows.Forms.Button();
this.wnd_action_destroy = new System.Windows.Forms.Button();
this.wnd_action_overlay = new System.Windows.Forms.Button();
this.wnd_action_front = new System.Windows.Forms.Button();
this.wnd_action_enabled = new System.Windows.Forms.CheckBox();
this.wnd_action_title_get = new System.Windows.Forms.Button();
this.wnd_action_title_set = new System.Windows.Forms.Button();
this.wnd_select_title_box = new System.Windows.Forms.TextBox();
this.wnd_selet_class_button = new System.Windows.Forms.Button();
this.wnd_select_class_button = new System.Windows.Forms.Button();
this.wnd_select_title_button = new System.Windows.Forms.Button();
this.wnd_select_selected = new System.Windows.Forms.Label();
this.wnd_select_self = new System.Windows.Forms.Button();
this.wnd = new System.Windows.Forms.GroupBox();
this.wnd_select_parent = new System.Windows.Forms.Button();
this.wnd_select_child = new System.Windows.Forms.Button();
this.wnd_select_list = new System.Windows.Forms.Button();
this.wnd_action_overlay = new System.Windows.Forms.CheckBox();
this.wnd_action_style = new System.Windows.Forms.ComboBox();
this.wnd_action_visible = new System.Windows.Forms.CheckBox();
this.wnd_action_icon = new System.Windows.Forms.Panel();
this.wnd_select_class_box = new System.Windows.Forms.TextBox();
this.screen = new System.Windows.Forms.GroupBox();
this.screen_draw = new System.Windows.Forms.Button();
this.screen_get = new System.Windows.Forms.Button();
this.screen_img = new System.Windows.Forms.Panel();
this.reader = new System.Windows.Forms.GroupBox();
this.readerFlow = new System.Windows.Forms.FlowLayoutPanel();
this.desk = new System.Windows.Forms.GroupBox();
this.desk_draw = new System.Windows.Forms.Button();
this.desk_set = new System.Windows.Forms.Button();
this.desk_get = new System.Windows.Forms.Button();
this.desk_back = new System.Windows.Forms.Panel();
this.readerUpdate = new System.Windows.Forms.Timer(this.components);
this.time = new System.Windows.Forms.GroupBox();
this.time_set = new System.Windows.Forms.Button();
this.time_select = new System.Windows.Forms.DateTimePicker();
this.keyboard.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.wnd_action_pos_h_bar)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.wnd_action_pos_w_bar)).BeginInit();
@ -74,31 +95,22 @@
this.mouse.SuspendLayout();
this.power.SuspendLayout();
this.wnd.SuspendLayout();
this.screen.SuspendLayout();
this.reader.SuspendLayout();
this.desk.SuspendLayout();
this.time.SuspendLayout();
this.SuspendLayout();
//
// exit
//
this.exit.BackColor = System.Drawing.Color.Black;
this.exit.Font = new System.Drawing.Font("Microsoft Sans Serif", 36F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.exit.ForeColor = System.Drawing.Color.White;
this.exit.Location = new System.Drawing.Point(264, 117);
this.exit.Name = "exit";
this.exit.Size = new System.Drawing.Size(35, 37);
this.exit.TabIndex = 9;
this.exit.Text = "°";
this.exit.UseVisualStyleBackColor = false;
this.exit.Click += new System.EventHandler(this.Exit_Click);
this.exit.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Exit_MouseDown);
this.exit.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Exit_MouseMove);
this.exit.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Exit_MouseUp);
//
// keyboard_log
//
this.keyboard_log.Location = new System.Drawing.Point(6, 42);
this.keyboard_log.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.keyboard_log.Location = new System.Drawing.Point(7, 48);
this.keyboard_log.Multiline = true;
this.keyboard_log.Name = "keyboard_log";
this.keyboard_log.ReadOnly = true;
this.keyboard_log.Size = new System.Drawing.Size(286, 123);
this.keyboard_log.Size = new System.Drawing.Size(333, 133);
this.keyboard_log.TabIndex = 2;
this.keyboard_log.TextChanged += new System.EventHandler(this.Keyboard_log_TextChanged);
//
@ -106,9 +118,9 @@
//
this.keyboard.Controls.Add(this.keyboard_log);
this.keyboard.Controls.Add(this.keyboard_enabled);
this.keyboard.Location = new System.Drawing.Point(264, 160);
this.keyboard.Location = new System.Drawing.Point(308, 224);
this.keyboard.Name = "keyboard";
this.keyboard.Size = new System.Drawing.Size(298, 171);
this.keyboard.Size = new System.Drawing.Size(348, 189);
this.keyboard.TabIndex = 8;
this.keyboard.TabStop = false;
this.keyboard.Text = "CC-Functions.W32.KeyboardHook";
@ -116,9 +128,9 @@
// keyboard_enabled
//
this.keyboard_enabled.AutoSize = true;
this.keyboard_enabled.Location = new System.Drawing.Point(6, 19);
this.keyboard_enabled.Location = new System.Drawing.Point(7, 22);
this.keyboard_enabled.Name = "keyboard_enabled";
this.keyboard_enabled.Size = new System.Drawing.Size(65, 17);
this.keyboard_enabled.Size = new System.Drawing.Size(68, 19);
this.keyboard_enabled.TabIndex = 0;
this.keyboard_enabled.Text = "Enabled";
this.keyboard_enabled.UseVisualStyleBackColor = true;
@ -126,20 +138,23 @@
//
// mouse_log
//
this.mouse_log.Location = new System.Drawing.Point(6, 42);
this.mouse_log.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.mouse_log.Location = new System.Drawing.Point(7, 48);
this.mouse_log.Multiline = true;
this.mouse_log.Name = "mouse_log";
this.mouse_log.ReadOnly = true;
this.mouse_log.Size = new System.Drawing.Size(245, 95);
this.mouse_log.Size = new System.Drawing.Size(333, 148);
this.mouse_log.TabIndex = 1;
this.mouse_log.TextChanged += new System.EventHandler(this.Mouse_log_TextChanged);
//
// mouse_enabled
//
this.mouse_enabled.AutoSize = true;
this.mouse_enabled.Location = new System.Drawing.Point(6, 19);
this.mouse_enabled.Location = new System.Drawing.Point(7, 22);
this.mouse_enabled.Name = "mouse_enabled";
this.mouse_enabled.Size = new System.Drawing.Size(65, 17);
this.mouse_enabled.Size = new System.Drawing.Size(68, 19);
this.mouse_enabled.TabIndex = 0;
this.mouse_enabled.Text = "Enabled";
this.mouse_enabled.UseVisualStyleBackColor = true;
@ -147,73 +162,82 @@
//
// wnd_action_pos_h_label
//
this.wnd_action_pos_h_label.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.wnd_action_pos_h_label.AutoSize = true;
this.wnd_action_pos_h_label.Location = new System.Drawing.Point(116, 185);
this.wnd_action_pos_h_label.Location = new System.Drawing.Point(135, 284);
this.wnd_action_pos_h_label.Name = "wnd_action_pos_h_label";
this.wnd_action_pos_h_label.Size = new System.Drawing.Size(18, 13);
this.wnd_action_pos_h_label.Size = new System.Drawing.Size(19, 15);
this.wnd_action_pos_h_label.TabIndex = 19;
this.wnd_action_pos_h_label.Text = "H:";
//
// wnd_action_pos_w_label
//
this.wnd_action_pos_w_label.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.wnd_action_pos_w_label.AutoSize = true;
this.wnd_action_pos_w_label.Location = new System.Drawing.Point(116, 161);
this.wnd_action_pos_w_label.Location = new System.Drawing.Point(135, 256);
this.wnd_action_pos_w_label.Name = "wnd_action_pos_w_label";
this.wnd_action_pos_w_label.Size = new System.Drawing.Size(21, 13);
this.wnd_action_pos_w_label.Size = new System.Drawing.Size(21, 15);
this.wnd_action_pos_w_label.TabIndex = 18;
this.wnd_action_pos_w_label.Text = "W:";
//
// wnd_action_pos_h_bar
//
this.wnd_action_pos_h_bar.Location = new System.Drawing.Point(136, 185);
this.wnd_action_pos_h_bar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.wnd_action_pos_h_bar.Location = new System.Drawing.Point(159, 284);
this.wnd_action_pos_h_bar.Name = "wnd_action_pos_h_bar";
this.wnd_action_pos_h_bar.Size = new System.Drawing.Size(104, 45);
this.wnd_action_pos_h_bar.Size = new System.Drawing.Size(121, 45);
this.wnd_action_pos_h_bar.TabIndex = 21;
//
// wnd_action_pos_w_bar
//
this.wnd_action_pos_w_bar.Location = new System.Drawing.Point(136, 161);
this.wnd_action_pos_w_bar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.wnd_action_pos_w_bar.Location = new System.Drawing.Point(159, 256);
this.wnd_action_pos_w_bar.Name = "wnd_action_pos_w_bar";
this.wnd_action_pos_w_bar.Size = new System.Drawing.Size(104, 45);
this.wnd_action_pos_w_bar.Size = new System.Drawing.Size(121, 45);
this.wnd_action_pos_w_bar.TabIndex = 20;
//
// wnd_action_pos_y_label
//
this.wnd_action_pos_y_label.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.wnd_action_pos_y_label.AutoSize = true;
this.wnd_action_pos_y_label.Location = new System.Drawing.Point(6, 185);
this.wnd_action_pos_y_label.Location = new System.Drawing.Point(7, 284);
this.wnd_action_pos_y_label.Name = "wnd_action_pos_y_label";
this.wnd_action_pos_y_label.Size = new System.Drawing.Size(17, 13);
this.wnd_action_pos_y_label.Size = new System.Drawing.Size(17, 15);
this.wnd_action_pos_y_label.TabIndex = 15;
this.wnd_action_pos_y_label.Text = "Y:";
//
// wnd_action_pos_x_label
//
this.wnd_action_pos_x_label.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.wnd_action_pos_x_label.AutoSize = true;
this.wnd_action_pos_x_label.Location = new System.Drawing.Point(6, 161);
this.wnd_action_pos_x_label.Location = new System.Drawing.Point(7, 256);
this.wnd_action_pos_x_label.Name = "wnd_action_pos_x_label";
this.wnd_action_pos_x_label.Size = new System.Drawing.Size(17, 13);
this.wnd_action_pos_x_label.Size = new System.Drawing.Size(17, 15);
this.wnd_action_pos_x_label.TabIndex = 13;
this.wnd_action_pos_x_label.Text = "X:";
//
// wnd_action_pos_y_bar
//
this.wnd_action_pos_y_bar.Location = new System.Drawing.Point(17, 185);
this.wnd_action_pos_y_bar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.wnd_action_pos_y_bar.Location = new System.Drawing.Point(20, 284);
this.wnd_action_pos_y_bar.Name = "wnd_action_pos_y_bar";
this.wnd_action_pos_y_bar.Size = new System.Drawing.Size(104, 45);
this.wnd_action_pos_y_bar.Size = new System.Drawing.Size(121, 45);
this.wnd_action_pos_y_bar.TabIndex = 17;
//
// wnd_action_pos_x_bar
//
this.wnd_action_pos_x_bar.Location = new System.Drawing.Point(17, 161);
this.wnd_action_pos_x_bar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.wnd_action_pos_x_bar.Location = new System.Drawing.Point(20, 256);
this.wnd_action_pos_x_bar.Name = "wnd_action_pos_x_bar";
this.wnd_action_pos_x_bar.Size = new System.Drawing.Size(104, 45);
this.wnd_action_pos_x_bar.Size = new System.Drawing.Size(121, 45);
this.wnd_action_pos_x_bar.TabIndex = 16;
//
// wnd_action_pos
//
this.wnd_action_pos.Location = new System.Drawing.Point(87, 135);
this.wnd_action_pos.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.wnd_action_pos.Location = new System.Drawing.Point(101, 226);
this.wnd_action_pos.Name = "wnd_action_pos";
this.wnd_action_pos.Size = new System.Drawing.Size(75, 23);
this.wnd_action_pos.Size = new System.Drawing.Size(87, 27);
this.wnd_action_pos.TabIndex = 14;
this.wnd_action_pos.Text = "Set Position";
this.wnd_action_pos.UseVisualStyleBackColor = true;
@ -223,9 +247,9 @@
//
this.mouse.Controls.Add(this.mouse_log);
this.mouse.Controls.Add(this.mouse_enabled);
this.mouse.Location = new System.Drawing.Point(305, 11);
this.mouse.Location = new System.Drawing.Point(308, 13);
this.mouse.Name = "mouse";
this.mouse.Size = new System.Drawing.Size(257, 143);
this.mouse.Size = new System.Drawing.Size(348, 204);
this.mouse.TabIndex = 7;
this.mouse.TabStop = false;
this.mouse.Text = "CC-Functions.W32.MouseHook";
@ -239,21 +263,23 @@
this.power.Controls.Add(this.power_reason_box);
this.power.Controls.Add(this.power_mode_label);
this.power.Controls.Add(this.power_mode_box);
this.power.Location = new System.Drawing.Point(12, 11);
this.power.Location = new System.Drawing.Point(14, 13);
this.power.Name = "power";
this.power.Size = new System.Drawing.Size(287, 100);
this.power.Size = new System.Drawing.Size(287, 115);
this.power.TabIndex = 5;
this.power.TabStop = false;
this.power.Text = "CC-Functions.W32.Power";
//
// power_execute
//
this.power_execute.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.power_execute.BackColor = System.Drawing.Color.DarkRed;
this.power_execute.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.power_execute.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.power_execute.ForeColor = System.Drawing.Color.White;
this.power_execute.Location = new System.Drawing.Point(200, 19);
this.power_execute.Location = new System.Drawing.Point(185, 22);
this.power_execute.Name = "power_execute";
this.power_execute.Size = new System.Drawing.Size(81, 75);
this.power_execute.Size = new System.Drawing.Size(94, 87);
this.power_execute.TabIndex = 6;
this.power_execute.Text = "DO IT";
this.power_execute.UseVisualStyleBackColor = false;
@ -262,59 +288,62 @@
// power_reason_label
//
this.power_reason_label.AutoSize = true;
this.power_reason_label.Location = new System.Drawing.Point(6, 49);
this.power_reason_label.Location = new System.Drawing.Point(7, 57);
this.power_reason_label.Name = "power_reason_label";
this.power_reason_label.Size = new System.Drawing.Size(44, 13);
this.power_reason_label.Size = new System.Drawing.Size(45, 15);
this.power_reason_label.TabIndex = 5;
this.power_reason_label.Text = "Reason";
//
// power_mod_label
//
this.power_mod_label.AutoSize = true;
this.power_mod_label.Location = new System.Drawing.Point(6, 76);
this.power_mod_label.Location = new System.Drawing.Point(7, 88);
this.power_mod_label.Name = "power_mod_label";
this.power_mod_label.Size = new System.Drawing.Size(28, 13);
this.power_mod_label.Size = new System.Drawing.Size(32, 15);
this.power_mod_label.TabIndex = 4;
this.power_mod_label.Text = "Mod";
//
// power_mod_box
//
this.power_mod_box.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.power_mod_box.FormattingEnabled = true;
this.power_mod_box.Location = new System.Drawing.Point(56, 73);
this.power_mod_box.Location = new System.Drawing.Point(65, 84);
this.power_mod_box.Name = "power_mod_box";
this.power_mod_box.Size = new System.Drawing.Size(138, 21);
this.power_mod_box.Size = new System.Drawing.Size(112, 23);
this.power_mod_box.TabIndex = 2;
//
// power_reason_box
//
this.power_reason_box.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.power_reason_box.FormattingEnabled = true;
this.power_reason_box.Location = new System.Drawing.Point(56, 46);
this.power_reason_box.Location = new System.Drawing.Point(65, 53);
this.power_reason_box.Name = "power_reason_box";
this.power_reason_box.Size = new System.Drawing.Size(138, 21);
this.power_reason_box.Size = new System.Drawing.Size(112, 23);
this.power_reason_box.TabIndex = 3;
//
// power_mode_label
//
this.power_mode_label.AutoSize = true;
this.power_mode_label.Location = new System.Drawing.Point(6, 22);
this.power_mode_label.Location = new System.Drawing.Point(7, 25);
this.power_mode_label.Name = "power_mode_label";
this.power_mode_label.Size = new System.Drawing.Size(34, 13);
this.power_mode_label.Size = new System.Drawing.Size(38, 15);
this.power_mode_label.TabIndex = 1;
this.power_mode_label.Text = "Mode";
//
// power_mode_box
//
this.power_mode_box.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.power_mode_box.FormattingEnabled = true;
this.power_mode_box.Location = new System.Drawing.Point(56, 19);
this.power_mode_box.Location = new System.Drawing.Point(65, 22);
this.power_mode_box.Name = "power_mode_box";
this.power_mode_box.Size = new System.Drawing.Size(138, 21);
this.power_mode_box.Size = new System.Drawing.Size(112, 23);
this.power_mode_box.TabIndex = 0;
//
// wnd_select_mouse
//
this.wnd_select_mouse.Location = new System.Drawing.Point(190, 19);
this.wnd_select_mouse.Location = new System.Drawing.Point(222, 22);
this.wnd_select_mouse.Name = "wnd_select_mouse";
this.wnd_select_mouse.Size = new System.Drawing.Size(50, 23);
this.wnd_select_mouse.Size = new System.Drawing.Size(58, 27);
this.wnd_select_mouse.TabIndex = 12;
this.wnd_select_mouse.Text = "Mouse";
this.wnd_select_mouse.UseVisualStyleBackColor = true;
@ -322,29 +351,21 @@
//
// wnd_action_destroy
//
this.wnd_action_destroy.Location = new System.Drawing.Point(6, 135);
this.wnd_action_destroy.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.wnd_action_destroy.Location = new System.Drawing.Point(7, 226);
this.wnd_action_destroy.Name = "wnd_action_destroy";
this.wnd_action_destroy.Size = new System.Drawing.Size(75, 23);
this.wnd_action_destroy.Size = new System.Drawing.Size(87, 27);
this.wnd_action_destroy.TabIndex = 2;
this.wnd_action_destroy.Text = "Destroy";
this.wnd_action_destroy.UseVisualStyleBackColor = true;
this.wnd_action_destroy.Click += new System.EventHandler(this.Wnd_action_destroy_Click);
//
// wnd_action_overlay
//
this.wnd_action_overlay.Location = new System.Drawing.Point(158, 106);
this.wnd_action_overlay.Name = "wnd_action_overlay";
this.wnd_action_overlay.Size = new System.Drawing.Size(79, 23);
this.wnd_action_overlay.TabIndex = 11;
this.wnd_action_overlay.Text = "Overlay";
this.wnd_action_overlay.UseVisualStyleBackColor = true;
this.wnd_action_overlay.Click += new System.EventHandler(this.Wnd_action_overlay_Click);
//
// wnd_action_front
//
this.wnd_action_front.Location = new System.Drawing.Point(77, 106);
this.wnd_action_front.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.wnd_action_front.Location = new System.Drawing.Point(196, 226);
this.wnd_action_front.Name = "wnd_action_front";
this.wnd_action_front.Size = new System.Drawing.Size(75, 23);
this.wnd_action_front.Size = new System.Drawing.Size(84, 27);
this.wnd_action_front.TabIndex = 10;
this.wnd_action_front.Text = "To Front";
this.wnd_action_front.UseVisualStyleBackColor = true;
@ -352,10 +373,11 @@
//
// wnd_action_enabled
//
this.wnd_action_enabled.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.wnd_action_enabled.AutoSize = true;
this.wnd_action_enabled.Location = new System.Drawing.Point(6, 110);
this.wnd_action_enabled.Location = new System.Drawing.Point(7, 167);
this.wnd_action_enabled.Name = "wnd_action_enabled";
this.wnd_action_enabled.Size = new System.Drawing.Size(65, 17);
this.wnd_action_enabled.Size = new System.Drawing.Size(68, 19);
this.wnd_action_enabled.TabIndex = 9;
this.wnd_action_enabled.Text = "Enabled";
this.wnd_action_enabled.UseVisualStyleBackColor = true;
@ -363,9 +385,10 @@
//
// wnd_action_title_get
//
this.wnd_action_title_get.Location = new System.Drawing.Point(200, 77);
this.wnd_action_title_get.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.wnd_action_title_get.Location = new System.Drawing.Point(237, 159);
this.wnd_action_title_get.Name = "wnd_action_title_get";
this.wnd_action_title_get.Size = new System.Drawing.Size(37, 23);
this.wnd_action_title_get.Size = new System.Drawing.Size(43, 27);
this.wnd_action_title_get.TabIndex = 8;
this.wnd_action_title_get.Text = "Get";
this.wnd_action_title_get.UseVisualStyleBackColor = true;
@ -373,9 +396,9 @@
//
// wnd_action_title_set
//
this.wnd_action_title_set.Location = new System.Drawing.Point(200, 48);
this.wnd_action_title_set.Location = new System.Drawing.Point(237, 55);
this.wnd_action_title_set.Name = "wnd_action_title_set";
this.wnd_action_title_set.Size = new System.Drawing.Size(37, 23);
this.wnd_action_title_set.Size = new System.Drawing.Size(43, 27);
this.wnd_action_title_set.TabIndex = 7;
this.wnd_action_title_set.Text = "Set";
this.wnd_action_title_set.UseVisualStyleBackColor = true;
@ -383,26 +406,26 @@
//
// wnd_select_title_box
//
this.wnd_select_title_box.Location = new System.Drawing.Point(93, 50);
this.wnd_select_title_box.Location = new System.Drawing.Point(108, 58);
this.wnd_select_title_box.Name = "wnd_select_title_box";
this.wnd_select_title_box.Size = new System.Drawing.Size(101, 20);
this.wnd_select_title_box.Size = new System.Drawing.Size(121, 23);
this.wnd_select_title_box.TabIndex = 6;
//
// wnd_selet_class_button
// wnd_select_class_button
//
this.wnd_selet_class_button.Location = new System.Drawing.Point(6, 77);
this.wnd_selet_class_button.Name = "wnd_selet_class_button";
this.wnd_selet_class_button.Size = new System.Drawing.Size(81, 23);
this.wnd_selet_class_button.TabIndex = 4;
this.wnd_selet_class_button.Text = "Select (class):";
this.wnd_selet_class_button.UseVisualStyleBackColor = true;
this.wnd_selet_class_button.Click += new System.EventHandler(this.Wnd_selet_class_button_Click);
this.wnd_select_class_button.Location = new System.Drawing.Point(7, 89);
this.wnd_select_class_button.Name = "wnd_select_class_button";
this.wnd_select_class_button.Size = new System.Drawing.Size(94, 27);
this.wnd_select_class_button.TabIndex = 4;
this.wnd_select_class_button.Text = "Select (class):";
this.wnd_select_class_button.UseVisualStyleBackColor = true;
this.wnd_select_class_button.Click += new System.EventHandler(this.Wnd_select_class_button_Click);
//
// wnd_select_title_button
//
this.wnd_select_title_button.Location = new System.Drawing.Point(6, 48);
this.wnd_select_title_button.Location = new System.Drawing.Point(7, 55);
this.wnd_select_title_button.Name = "wnd_select_title_button";
this.wnd_select_title_button.Size = new System.Drawing.Size(81, 23);
this.wnd_select_title_button.Size = new System.Drawing.Size(94, 27);
this.wnd_select_title_button.TabIndex = 2;
this.wnd_select_title_button.Text = "Select (title):";
this.wnd_select_title_button.UseVisualStyleBackColor = true;
@ -411,17 +434,17 @@
// wnd_select_selected
//
this.wnd_select_selected.AutoSize = true;
this.wnd_select_selected.Location = new System.Drawing.Point(93, 24);
this.wnd_select_selected.Location = new System.Drawing.Point(108, 28);
this.wnd_select_selected.Name = "wnd_select_selected";
this.wnd_select_selected.Size = new System.Drawing.Size(91, 13);
this.wnd_select_selected.Size = new System.Drawing.Size(93, 15);
this.wnd_select_selected.TabIndex = 1;
this.wnd_select_selected.Text = "Selected: 123456";
//
// wnd_select_self
//
this.wnd_select_self.Location = new System.Drawing.Point(6, 19);
this.wnd_select_self.Location = new System.Drawing.Point(7, 22);
this.wnd_select_self.Name = "wnd_select_self";
this.wnd_select_self.Size = new System.Drawing.Size(81, 23);
this.wnd_select_self.Size = new System.Drawing.Size(94, 27);
this.wnd_select_self.TabIndex = 0;
this.wnd_select_self.Text = "Select self";
this.wnd_select_self.UseVisualStyleBackColor = true;
@ -429,6 +452,13 @@
//
// wnd
//
this.wnd.Controls.Add(this.wnd_select_parent);
this.wnd.Controls.Add(this.wnd_select_child);
this.wnd.Controls.Add(this.wnd_select_list);
this.wnd.Controls.Add(this.wnd_action_overlay);
this.wnd.Controls.Add(this.wnd_action_style);
this.wnd.Controls.Add(this.wnd_action_visible);
this.wnd.Controls.Add(this.wnd_action_icon);
this.wnd.Controls.Add(this.wnd_action_pos_h_label);
this.wnd.Controls.Add(this.wnd_action_pos_w_label);
this.wnd.Controls.Add(this.wnd_action_pos_h_bar);
@ -440,44 +470,280 @@
this.wnd.Controls.Add(this.wnd_action_pos);
this.wnd.Controls.Add(this.wnd_select_mouse);
this.wnd.Controls.Add(this.wnd_action_destroy);
this.wnd.Controls.Add(this.wnd_action_overlay);
this.wnd.Controls.Add(this.wnd_action_front);
this.wnd.Controls.Add(this.wnd_action_enabled);
this.wnd.Controls.Add(this.wnd_action_title_get);
this.wnd.Controls.Add(this.wnd_action_title_set);
this.wnd.Controls.Add(this.wnd_select_title_box);
this.wnd.Controls.Add(this.wnd_select_class_box);
this.wnd.Controls.Add(this.wnd_selet_class_button);
this.wnd.Controls.Add(this.wnd_select_class_button);
this.wnd.Controls.Add(this.wnd_select_title_button);
this.wnd.Controls.Add(this.wnd_select_selected);
this.wnd.Controls.Add(this.wnd_select_self);
this.wnd.Location = new System.Drawing.Point(12, 117);
this.wnd.Location = new System.Drawing.Point(14, 135);
this.wnd.Name = "wnd";
this.wnd.Size = new System.Drawing.Size(246, 214);
this.wnd.Size = new System.Drawing.Size(287, 345);
this.wnd.TabIndex = 6;
this.wnd.TabStop = false;
this.wnd.Text = "CC-Functions.W32.Wnd32";
//
// wnd_select_parent
//
this.wnd_select_parent.Location = new System.Drawing.Point(207, 122);
this.wnd_select_parent.Name = "wnd_select_parent";
this.wnd_select_parent.Size = new System.Drawing.Size(74, 27);
this.wnd_select_parent.TabIndex = 27;
this.wnd_select_parent.Text = "Parent";
this.wnd_select_parent.UseVisualStyleBackColor = true;
this.wnd_select_parent.Click += new System.EventHandler(this.wnd_select_parent_Click);
//
// wnd_select_child
//
this.wnd_select_child.Location = new System.Drawing.Point(107, 122);
this.wnd_select_child.Name = "wnd_select_child";
this.wnd_select_child.Size = new System.Drawing.Size(94, 27);
this.wnd_select_child.TabIndex = 27;
this.wnd_select_child.Text = "Select (childs)";
this.wnd_select_child.UseVisualStyleBackColor = true;
this.wnd_select_child.Click += new System.EventHandler(this.wnd_select_child_Click);
//
// wnd_select_list
//
this.wnd_select_list.Location = new System.Drawing.Point(7, 122);
this.wnd_select_list.Name = "wnd_select_list";
this.wnd_select_list.Size = new System.Drawing.Size(94, 27);
this.wnd_select_list.TabIndex = 26;
this.wnd_select_list.Text = "Select (list)";
this.wnd_select_list.UseVisualStyleBackColor = true;
this.wnd_select_list.Click += new System.EventHandler(this.wnd_select_list_Click);
//
// wnd_action_overlay
//
this.wnd_action_overlay.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.wnd_action_overlay.AutoSize = true;
this.wnd_action_overlay.Location = new System.Drawing.Point(162, 167);
this.wnd_action_overlay.Name = "wnd_action_overlay";
this.wnd_action_overlay.Size = new System.Drawing.Size(66, 19);
this.wnd_action_overlay.TabIndex = 25;
this.wnd_action_overlay.Text = "Overlay";
this.wnd_action_overlay.UseVisualStyleBackColor = true;
this.wnd_action_overlay.CheckedChanged += new System.EventHandler(this.wnd_action_overlay_CheckedChanged);
//
// wnd_action_style
//
this.wnd_action_style.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.wnd_action_style.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.wnd_action_style.FormattingEnabled = true;
this.wnd_action_style.Location = new System.Drawing.Point(7, 195);
this.wnd_action_style.Name = "wnd_action_style";
this.wnd_action_style.Size = new System.Drawing.Size(238, 23);
this.wnd_action_style.TabIndex = 24;
this.wnd_action_style.SelectedIndexChanged += new System.EventHandler(this.Wnd_action_style_SelectedIndexChanged);
//
// wnd_action_visible
//
this.wnd_action_visible.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.wnd_action_visible.AutoSize = true;
this.wnd_action_visible.Location = new System.Drawing.Point(90, 167);
this.wnd_action_visible.Name = "wnd_action_visible";
this.wnd_action_visible.Size = new System.Drawing.Size(60, 19);
this.wnd_action_visible.TabIndex = 23;
this.wnd_action_visible.Text = "Visible";
this.wnd_action_visible.UseVisualStyleBackColor = true;
this.wnd_action_visible.CheckedChanged += new System.EventHandler(this.Wnd_action_visible_CheckedChanged);
//
// wnd_action_icon
//
this.wnd_action_icon.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.wnd_action_icon.BackColor = System.Drawing.SystemColors.ControlLight;
this.wnd_action_icon.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.wnd_action_icon.Location = new System.Drawing.Point(253, 193);
this.wnd_action_icon.Name = "wnd_action_icon";
this.wnd_action_icon.Size = new System.Drawing.Size(27, 27);
this.wnd_action_icon.TabIndex = 22;
//
// wnd_select_class_box
//
this.wnd_select_class_box.Location = new System.Drawing.Point(93, 79);
this.wnd_select_class_box.Location = new System.Drawing.Point(108, 91);
this.wnd_select_class_box.Name = "wnd_select_class_box";
this.wnd_select_class_box.Size = new System.Drawing.Size(101, 20);
this.wnd_select_class_box.Size = new System.Drawing.Size(171, 23);
this.wnd_select_class_box.TabIndex = 5;
//
// Form1
// screen
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.screen.Controls.Add(this.screen_draw);
this.screen.Controls.Add(this.screen_get);
this.screen.Controls.Add(this.screen_img);
this.screen.Location = new System.Drawing.Point(663, 14);
this.screen.Name = "screen";
this.screen.Size = new System.Drawing.Size(282, 202);
this.screen.TabIndex = 10;
this.screen.TabStop = false;
this.screen.Text = "CC-Functions.W32.ScreenMan";
//
// screen_draw
//
this.screen_draw.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.screen_draw.Location = new System.Drawing.Point(188, 168);
this.screen_draw.Name = "screen_draw";
this.screen_draw.Size = new System.Drawing.Size(87, 27);
this.screen_draw.TabIndex = 3;
this.screen_draw.Text = "Draw";
this.screen_draw.UseVisualStyleBackColor = true;
this.screen_draw.Click += new System.EventHandler(this.screen_draw_Click);
//
// screen_get
//
this.screen_get.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.screen_get.Location = new System.Drawing.Point(7, 168);
this.screen_get.Name = "screen_get";
this.screen_get.Size = new System.Drawing.Size(87, 27);
this.screen_get.TabIndex = 2;
this.screen_get.Text = "Get";
this.screen_get.UseVisualStyleBackColor = true;
this.screen_get.Click += new System.EventHandler(this.screen_get_Click);
//
// screen_img
//
this.screen_img.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.screen_img.BackColor = System.Drawing.Color.White;
this.screen_img.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.screen_img.Location = new System.Drawing.Point(7, 22);
this.screen_img.Name = "screen_img";
this.screen_img.Size = new System.Drawing.Size(268, 140);
this.screen_img.TabIndex = 1;
//
// reader
//
this.reader.Controls.Add(this.readerFlow);
this.reader.Location = new System.Drawing.Point(308, 420);
this.reader.Name = "reader";
this.reader.Size = new System.Drawing.Size(637, 171);
this.reader.TabIndex = 11;
this.reader.TabStop = false;
this.reader.Text = "CC-Functions.W32.KeyboardReader";
//
// readerFlow
//
this.readerFlow.AutoScroll = true;
this.readerFlow.Dock = System.Windows.Forms.DockStyle.Fill;
this.readerFlow.Location = new System.Drawing.Point(3, 19);
this.readerFlow.Name = "readerFlow";
this.readerFlow.Size = new System.Drawing.Size(631, 149);
this.readerFlow.TabIndex = 0;
//
// desk
//
this.desk.Controls.Add(this.desk_draw);
this.desk.Controls.Add(this.desk_set);
this.desk.Controls.Add(this.desk_get);
this.desk.Controls.Add(this.desk_back);
this.desk.Location = new System.Drawing.Point(663, 224);
this.desk.Name = "desk";
this.desk.Size = new System.Drawing.Size(282, 189);
this.desk.TabIndex = 11;
this.desk.TabStop = false;
this.desk.Text = "CC-Functions.W32.DeskMan";
//
// desk_draw
//
this.desk_draw.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.desk_draw.Location = new System.Drawing.Point(188, 156);
this.desk_draw.Name = "desk_draw";
this.desk_draw.Size = new System.Drawing.Size(87, 27);
this.desk_draw.TabIndex = 3;
this.desk_draw.Text = "Draw";
this.desk_draw.UseVisualStyleBackColor = true;
this.desk_draw.Click += new System.EventHandler(this.desk_draw_Click);
//
// desk_set
//
this.desk_set.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.desk_set.Location = new System.Drawing.Point(101, 156);
this.desk_set.Name = "desk_set";
this.desk_set.Size = new System.Drawing.Size(79, 27);
this.desk_set.TabIndex = 2;
this.desk_set.Text = "Set";
this.desk_set.UseVisualStyleBackColor = true;
this.desk_set.Click += new System.EventHandler(this.desk_set_Click);
//
// desk_get
//
this.desk_get.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.desk_get.Location = new System.Drawing.Point(7, 156);
this.desk_get.Name = "desk_get";
this.desk_get.Size = new System.Drawing.Size(87, 27);
this.desk_get.TabIndex = 1;
this.desk_get.Text = "Get";
this.desk_get.UseVisualStyleBackColor = true;
this.desk_get.Click += new System.EventHandler(this.desk_get_Click);
//
// desk_back
//
this.desk_back.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.desk_back.BackColor = System.Drawing.Color.White;
this.desk_back.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.desk_back.Location = new System.Drawing.Point(7, 22);
this.desk_back.Name = "desk_back";
this.desk_back.Size = new System.Drawing.Size(268, 127);
this.desk_back.TabIndex = 0;
//
// readerUpdate
//
this.readerUpdate.Enabled = true;
this.readerUpdate.Interval = 50;
this.readerUpdate.Tick += new System.EventHandler(this.readerUpdate_Tick);
//
// time
//
this.time.Controls.Add(this.time_set);
this.time.Controls.Add(this.time_select);
this.time.Location = new System.Drawing.Point(14, 486);
this.time.Name = "time";
this.time.Size = new System.Drawing.Size(287, 102);
this.time.TabIndex = 12;
this.time.TabStop = false;
this.time.Text = "CC-Functions.W32.Time";
//
// time_set
//
this.time_set.Location = new System.Drawing.Point(217, 22);
this.time_set.Name = "time_set";
this.time_set.Size = new System.Drawing.Size(64, 27);
this.time_set.TabIndex = 1;
this.time_set.Text = "Set";
this.time_set.UseVisualStyleBackColor = true;
this.time_set.Click += new System.EventHandler(this.time_set_Click);
//
// time_select
//
this.time_select.Location = new System.Drawing.Point(6, 27);
this.time_select.Name = "time_select";
this.time_select.Size = new System.Drawing.Size(205, 23);
this.time_select.TabIndex = 0;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(574, 342);
this.Controls.Add(this.exit);
this.ClientSize = new System.Drawing.Size(959, 595);
this.Controls.Add(this.time);
this.Controls.Add(this.desk);
this.Controls.Add(this.reader);
this.Controls.Add(this.screen);
this.Controls.Add(this.keyboard);
this.Controls.Add(this.mouse);
this.Controls.Add(this.power);
this.Controls.Add(this.wnd);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Name = "Form1";
this.Name = "MainForm";
this.ShowIcon = false;
this.Text = "CC-Functions.W32.Test";
this.keyboard.ResumeLayout(false);
this.keyboard.PerformLayout();
@ -491,13 +757,15 @@
this.power.PerformLayout();
this.wnd.ResumeLayout(false);
this.wnd.PerformLayout();
this.screen.ResumeLayout(false);
this.reader.ResumeLayout(false);
this.desk.ResumeLayout(false);
this.time.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button exit;
private System.Windows.Forms.TextBox keyboard_log;
private System.Windows.Forms.GroupBox keyboard;
private System.Windows.Forms.CheckBox keyboard_enabled;
@ -523,17 +791,38 @@
private System.Windows.Forms.ComboBox power_mode_box;
private System.Windows.Forms.Button wnd_select_mouse;
private System.Windows.Forms.Button wnd_action_destroy;
private System.Windows.Forms.Button wnd_action_overlay;
private System.Windows.Forms.Button wnd_action_front;
private System.Windows.Forms.CheckBox wnd_action_enabled;
private System.Windows.Forms.Button wnd_action_title_get;
private System.Windows.Forms.Button wnd_action_title_set;
private System.Windows.Forms.TextBox wnd_select_title_box;
private System.Windows.Forms.Button wnd_selet_class_button;
private System.Windows.Forms.Button wnd_select_class_button;
private System.Windows.Forms.Button wnd_select_title_button;
private System.Windows.Forms.Label wnd_select_selected;
private System.Windows.Forms.Button wnd_select_self;
private System.Windows.Forms.GroupBox wnd;
private System.Windows.Forms.TextBox wnd_select_class_box;
private System.Windows.Forms.Panel wnd_action_icon;
private System.Windows.Forms.CheckBox wnd_action_visible;
private System.Windows.Forms.ComboBox wnd_action_style;
private System.Windows.Forms.CheckBox wnd_action_overlay;
private System.Windows.Forms.Button wnd_select_list;
private System.Windows.Forms.GroupBox screen;
private System.Windows.Forms.GroupBox reader;
private System.Windows.Forms.GroupBox desk;
private System.Windows.Forms.FlowLayoutPanel readerFlow;
private System.Windows.Forms.Timer readerUpdate;
private System.Windows.Forms.Panel desk_back;
private System.Windows.Forms.Button desk_get;
private System.Windows.Forms.Button desk_set;
private System.Windows.Forms.Button desk_draw;
private System.Windows.Forms.Panel screen_img;
private System.Windows.Forms.Button screen_get;
private System.Windows.Forms.Button screen_draw;
private System.Windows.Forms.GroupBox time;
private System.Windows.Forms.DateTimePicker time_select;
private System.Windows.Forms.Button time_set;
private System.Windows.Forms.Button wnd_select_child;
private System.Windows.Forms.Button wnd_select_parent;
}
}

423
W32.Test/MainForm.cs Normal file
View File

@ -0,0 +1,423 @@
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using CC_Functions.W32.DCDrawer;
using CC_Functions.W32.Forms;
using CC_Functions.W32.Hooks;
using static CC_Functions.W32.Power;
namespace CC_Functions.W32.Test
{
public partial class MainForm : Form
{
private static Wnd32 _tmpWnd32Obj;
private static MainForm _mainF;
private static Wnd32 _wndSelectMouseCurrent;
private readonly KeyboardHook _kHook;
private readonly MouseHook _mHook;
private readonly Label[] _readerLabels;
public MainForm()
{
_wndSelectMouseCurrent = this.GetWnd32();
InitializeComponent();
_mainF = this;
_tmpWnd32Obj = Wnd32.FromForm(this);
#if DEBUG
_tmpWnd32Obj.Overlay = true;
#endif
set_up_box(power_mode_box, typeof(ShutdownMode));
set_up_box(power_reason_box, typeof(ShutdownReason));
set_up_box(power_mod_box, typeof(ShutdownMod));
_mHook = new MouseHook();
_kHook = new KeyboardHook();
wnd_action_pos_x_bar.Maximum = Screen.PrimaryScreen.Bounds.Width;
wnd_action_pos_y_bar.Maximum = Screen.PrimaryScreen.Bounds.Height;
wnd_action_pos_w_bar.Maximum = Screen.PrimaryScreen.Bounds.Width;
wnd_action_pos_h_bar.Maximum = Screen.PrimaryScreen.Bounds.Height;
wnd_action_style.DataSource = Enum.GetValues(typeof(FormWindowState));
wnd_action_style.SelectedItem = _tmpWnd32Obj.State;
_readerLabels = Enum.GetValues(typeof(Keys)).OfType<Keys>().OrderBy(s => s.ToString()).Select(s =>
{
Label lab = new Label {Tag = s};
readerFlow.Controls.Add(lab);
return lab;
}).ToArray();
Wnd_action_title_get_Click(null, null);
desk_get_Click(null, null);
screen_get_Click(null, null);
time_select.Value = DateTime.Now;
}
private Wnd32 TmpWnd
{
get => _tmpWnd32Obj;
set
{
_tmpWnd32Obj = value;
Wnd_action_title_get_Click(null, null);
}
}
private static void set_up_box(ComboBox box, Type enumT)
{
box.DataSource = Enum.GetNames(enumT);
Array tmp = Enum.GetValues(enumT);
box.Tag = new object[tmp.Length];
int i = 0;
foreach (object o in tmp)
{
((object[]) box.Tag)[i] = o;
i++;
}
}
private static object get_box_value(ListControl box) => ((object[]) box.Tag)[box.SelectedIndex];
private void Power_execute_Click(object sender, EventArgs e) => RaiseEvent(
(ShutdownMode) get_box_value(power_mode_box), (ShutdownReason) get_box_value(power_reason_box),
(ShutdownMod) get_box_value(power_mod_box));
private void Wnd_select_self_Click(object sender, EventArgs e) => TmpWnd = Wnd32.FromForm(this);
private void wnd_select_list_Click(object sender, EventArgs e) =>
TmpWnd = SelectBox.Show(Wnd32.Visible, "Please select a window") ?? TmpWnd;
private void wnd_select_parent_Click(object sender, EventArgs e) => TmpWnd = TmpWnd.Parent;
private void wnd_select_child_Click(object sender, EventArgs e)
{
if (TmpWnd.HWnd != Handle && !this.GetWnd32().Children.Contains(TmpWnd))
{
WindowState = FormWindowState.Minimized;
TmpWnd.Enabled = false;
}
Wnd32.FromForm(this).IsForeground = true;
Form frm = new Form
{
BackColor = Color.White,
Opacity = 0.4f,
FormBorderStyle = FormBorderStyle.None,
WindowState = FormWindowState.Maximized
};
Label lab = new Label {AutoSize = true};
frm.Controls.Add(lab);
Panel pan = new Panel {BackColor = Color.Red};
frm.Controls.Add(pan);
Wnd32[] children = TmpWnd.Children;
void UpdateGui(Point labelPosition)
{
lab.Text = $"{_wndSelectMouseCurrent.Title} ({_wndSelectMouseCurrent.HWnd})";
lab.Location = new Point(labelPosition.X + 5, labelPosition.Y + 5);
pan.Bounds = _wndSelectMouseCurrent.Position;
}
void MouseEventHandler(object sender1, MouseEventArgs e1)
{
Func<Wnd32, bool> checkWnd = s => s.Position.Contains(e1.Location);
if (children.Any(checkWnd))
{
_wndSelectMouseCurrent = children.First(checkWnd);
UpdateGui(Cursor.Position);
}
}
void EventHandler(object sender1, EventArgs e1)
{
frm.Hide();
frm.WindowState = FormWindowState.Minimized;
Wnd32 tmp = _wndSelectMouseCurrent;
TmpWnd.Enabled = true;
TmpWnd.IsForeground = true;
TmpWnd = tmp;
_mainF.WindowState = FormWindowState.Normal;
frm.Close();
}
void KeyEventHandler(object sender1, KeyEventArgs e1)
{
int tmp;
switch (e1.KeyCode)
{
case Keys.Escape:
frm.Close();
break;
case Keys.Up:
case Keys.Left:
tmp = Array.IndexOf(children, _wndSelectMouseCurrent);
if (tmp == 0)
tmp = children.Length;
tmp--;
_wndSelectMouseCurrent = children[tmp];
UpdateGui(_wndSelectMouseCurrent.Position.Location);
break;
case Keys.Down:
case Keys.Right:
tmp = Array.IndexOf(children, _wndSelectMouseCurrent);
tmp++;
if (tmp == children.Length)
tmp = 0;
_wndSelectMouseCurrent = children[tmp];
UpdateGui(_wndSelectMouseCurrent.Position.Location);
break;
}
}
frm.Click += EventHandler;
pan.Click += EventHandler;
lab.Click += EventHandler;
frm.MouseMove += MouseEventHandler;
pan.MouseMove += MouseEventHandler;
lab.MouseMove += MouseEventHandler;
frm.KeyDown += KeyEventHandler;
UpdateGui(Cursor.Position);
frm.Show();
_wndSelectMouseCurrent = frm.GetWnd32();
Cursor.Position = Cursor.Position;
frm.GetWnd32().Overlay = true;
}
private void Wnd_select_title_button_Click(object sender, EventArgs e) =>
TmpWnd = Wnd32.FromMetadata(null, wnd_select_title_box.Text);
private void Wnd_select_class_button_Click(object sender, EventArgs e) =>
TmpWnd = Wnd32.FromMetadata(wnd_select_class_box.Text);
private void Wnd_action_title_set_Click(object sender, EventArgs e) => TmpWnd.Title = wnd_select_title_box.Text;
private void Wnd_action_title_get_Click(object sender, EventArgs e)
{
if (!TmpWnd.StillExists)
TmpWnd = Wnd32.FromForm(this);
wnd_select_title_box.Text = TmpWnd.Title;
wnd_action_enabled.Checked = TmpWnd.Enabled;
wnd_select_selected.Text = $"Selected: {TmpWnd.HWnd}";
wnd_action_style.SelectedIndex = (int) TmpWnd.State;
wnd_select_class_box.Text = TmpWnd.ClassName;
wnd_action_visible.Checked = TmpWnd.Shown;
try
{
wnd_action_icon.BackgroundImage = TmpWnd.Icon.ToBitmap();
}
catch
{
wnd_action_icon.BackgroundImage = null;
}
try
{
wnd_action_pos_x_bar.Value = TmpWnd.Position.X;
}
catch
{
// ignored
}
try
{
wnd_action_pos_y_bar.Value = TmpWnd.Position.Y;
}
catch
{
// ignored
}
try
{
wnd_action_pos_w_bar.Value = TmpWnd.Position.Width;
}
catch
{
// ignored
}
try
{
wnd_action_pos_h_bar.Value = TmpWnd.Position.Height;
}
catch
{
// ignored
}
try
{
wnd_select_parent.Tag = TmpWnd.Parent;
wnd_select_parent.Enabled = true;
}
catch
{
wnd_select_parent.Enabled = false;
}
}
private void Wnd_action_enabled_CheckedChanged(object sender, EventArgs e) =>
TmpWnd.Enabled = wnd_action_enabled.Checked;
private void Wnd_action_visible_CheckedChanged(object sender, EventArgs e) =>
TmpWnd.Shown = wnd_action_visible.Checked;
private void Wnd_action_front_Click(object sender, EventArgs e) => TmpWnd.IsForeground = true;
private void Wnd_action_destroy_Click(object sender, EventArgs e) => TmpWnd.Destroy();
private void Wnd_select_mouse_Click(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
TmpWnd = Wnd32.FromForm(this);
TmpWnd.Enabled = false;
Form frm = new Form
{
BackColor = Color.White,
Opacity = 0.4f,
FormBorderStyle = FormBorderStyle.None,
WindowState = FormWindowState.Maximized
};
Label lab = new Label {AutoSize = true};
frm.Controls.Add(lab);
Panel pan = new Panel {BackColor = Color.Red};
frm.Controls.Add(pan);
void UpdateGui(Point labelPosition)
{
lab.Text = $"{_wndSelectMouseCurrent.Title} ({_wndSelectMouseCurrent.HWnd})";
lab.Location = new Point(labelPosition.X + 5, labelPosition.Y + 5);
pan.Bounds = _wndSelectMouseCurrent.Position;
}
void MouseEventHandler(object sender1, MouseEventArgs e1)
{
_wndSelectMouseCurrent = Wnd32.AllFromPoint(MousePosition, true).First(s => s != frm.GetWnd32());
UpdateGui(Cursor.Position);
}
void EventHandler(object sender1, EventArgs e1)
{
frm.Hide();
frm.WindowState = FormWindowState.Minimized;
Wnd32 tmp = _wndSelectMouseCurrent;
TmpWnd.Enabled = true;
TmpWnd.IsForeground = true;
TmpWnd = tmp;
_mainF.WindowState = FormWindowState.Normal;
frm.Close();
}
void KeyEventHandler(object sender1, KeyEventArgs e1)
{
if (e1.KeyCode == Keys.Escape)
frm.Close();
}
frm.Click += EventHandler;
pan.Click += EventHandler;
lab.Click += EventHandler;
frm.MouseMove += MouseEventHandler;
pan.MouseMove += MouseEventHandler;
lab.MouseMove += MouseEventHandler;
frm.KeyDown += KeyEventHandler;
frm.Show();
_wndSelectMouseCurrent = frm.GetWnd32();
Cursor.Position = Cursor.Position;
frm.GetWnd32().Overlay = true;
}
private void Mouse_enabled_CheckedChanged(object sender, EventArgs e)
{
if (mouse_enabled.Checked)
_mHook.OnMouse += MHook_OnMouse;
else
_mHook.OnMouse -= MHook_OnMouse;
}
private void MHook_OnMouse(MouseHookEventArgs args) =>
mouse_log.Text = $"{args.Message} -|- {args.Point}\r\n{mouse_log.Text}";
private void Mouse_log_TextChanged(object sender, EventArgs e) =>
mouse_log.Lines = mouse_log.Lines.Take(9).ToArray();
private void Keyboard_enabled_CheckedChanged(object sender, EventArgs e)
{
if (keyboard_enabled.Checked)
_kHook.OnKeyPress += KHook_OnKeyPress;
else
_kHook.OnKeyPress -= KHook_OnKeyPress;
}
private void KHook_OnKeyPress(KeyboardHookEventArgs args) =>
keyboard_log.Text = $"{args.Key}\r\n{keyboard_log.Text}";
private void Keyboard_log_TextChanged(object sender, EventArgs e) =>
keyboard_log.Lines = keyboard_log.Lines.Take(8).ToArray();
private void Wnd_action_pos_Click(object sender, EventArgs e) =>
TmpWnd.Position = new Rectangle(wnd_action_pos_x_bar.Value, wnd_action_pos_y_bar.Value,
wnd_action_pos_w_bar.Value, wnd_action_pos_h_bar.Value);
private void Wnd_action_style_SelectedIndexChanged(object sender, EventArgs e)
{
Enum.TryParse(wnd_action_style.SelectedValue.ToString(), out FormWindowState status);
TmpWnd.State = status;
}
private void wnd_action_overlay_CheckedChanged(object sender, EventArgs e) =>
TmpWnd.Overlay = wnd_action_overlay.Checked;
private void readerUpdate_Tick(object sender, EventArgs e)
{
foreach (Label s in _readerLabels)
{
Keys key = (Keys) s.Tag;
s.Text = $"{key.ToString()}: {key.IsDown()}";
}
}
private void desk_get_Click(object sender, EventArgs e) => desk_back.BackgroundImage = DeskMan.Wallpaper;
private void desk_draw_Click(object sender, EventArgs e)
{
using IDCDrawer drawer = DeskMan.CreateGraphics();
Graphics g = drawer.Graphics;
Pen eye = new Pen(new SolidBrush(Color.Red), 2);
g.DrawCurve(eye, new[] {MakePoint(20, 50), MakePoint(50, 65), MakePoint(80, 50)});
g.DrawCurve(eye, new[] {MakePoint(20, 50), MakePoint(50, 35), MakePoint(80, 50)});
g.DrawEllipse(eye,
new RectangleF(PointF.Subtract(MakePoint(50, 50), MakeSizeY(15, 15)), MakeSizeY(30, 30)));
}
private static PointF MakePoint(float xPercent, float yPercent) => new PointF(
Screen.PrimaryScreen.Bounds.Width * xPercent / 100,
Screen.PrimaryScreen.Bounds.Height * yPercent / 100);
private static SizeF MakeSizeY(float xPercent, float yPercent) => new SizeF(
Screen.PrimaryScreen.Bounds.Height * xPercent / 100,
Screen.PrimaryScreen.Bounds.Height * yPercent / 100);
private void desk_set_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "Images (*.jpg, *.jpeg, *.jpe, *.jfif, *.png)|*.jpg;*.jpeg;*.jpe;*.jfif;*.png";
if (dlg.ShowDialog() == DialogResult.OK) DeskMan.Wallpaper = Image.FromFile(dlg.FileName);
}
private void screen_get_Click(object sender, EventArgs e) =>
screen_img.BackgroundImage = ScreenMan.CaptureScreen();
private void screen_draw_Click(object sender, EventArgs e)
{
using IDCDrawer drawer = ScreenMan.GetDrawer(false);
Graphics g = drawer.Graphics;
Pen eye = new Pen(new SolidBrush(Color.Red), 2);
g.DrawCurve(eye, new[] {MakePoint(20, 50), MakePoint(50, 65), MakePoint(80, 50)});
g.DrawCurve(eye, new[] {MakePoint(20, 50), MakePoint(50, 35), MakePoint(80, 50)});
g.DrawEllipse(eye,
new RectangleF(PointF.Subtract(MakePoint(50, 50), MakeSizeY(15, 15)), MakeSizeY(30, 30)));
}
private void time_set_Click(object sender, EventArgs e) => Time.Set(time_select.Value);
}
}

60
W32.Test/MainForm.resx Normal file
View File

@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,22 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CC_Functions.W32.Test
{
static class Program
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Application.Run(new MainForm());
}
}
}
}

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("W32.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("W32.Test")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6121a6d3-7c73-4ede-a5a9-09dc52150824")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,63 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CC_Functions.W32.Test.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CC_Functions.W32.Test.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@ -1,117 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CC_Functions.W32.Test.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -1,90 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6121A6D3-7C73-4EDE-A5A9-09DC52150824}</ProjectGuid>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>WinExe</OutputType>
<RootNamespace>CC_Functions.W32.Test</RootNamespace>
<AssemblyName>CC_Functions.W32.Test</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<LangVersion>8</LangVersion>
<UseWindowsForms>true</UseWindowsForms>
<Deterministic>false</Deterministic>
<AssemblyVersion>1.1.*</AssemblyVersion>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>if exist "$(SolutionDir)Data\pkgtool.exe" ($(SolutionDir)Data\pkgtool.exe build --noLogo --binDir .) else if exist "%appdata%\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app\pkgtool.exe" ("%appdata%\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app\pkgtool.exe" build --noLogo --binDir .) else echo Cound not find Package build tools, skipping</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile></DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile></DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<ProjectReference Include="..\Misc\Misc.csproj" />
<ProjectReference Include="..\W32\W32.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\W32\W32.csproj">
<Project>{23de4ae0-5075-4ccc-8440-4d131ca0fbba}</Project>
<Name>W32</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>

View File

@ -0,0 +1,33 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace CC_Functions.W32.DCDrawer
{
public class DCBuffered : IDCDrawer
{
private readonly BufferedGraphics buffer;
private readonly DCUnbuffered drawer;
public DCBuffered(IntPtr ptr) : this(ptr, IntPtr.Zero)
{
}
public DCBuffered(IntPtr ptr, IntPtr hWnd)
{
drawer = new DCUnbuffered(ptr, hWnd);
buffer = BufferedGraphicsManager.Current.Allocate(drawer.Graphics, Screen.PrimaryScreen.Bounds);
Graphics = buffer.Graphics;
}
public Graphics Graphics { get; }
public void Dispose()
{
buffer.Render(drawer.Graphics);
Graphics.Dispose();
buffer.Dispose();
drawer.Dispose();
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Drawing;
using CC_Functions.W32.Native;
namespace CC_Functions.W32.DCDrawer
{
public class DCUnbuffered : IDCDrawer
{
private readonly IntPtr hWnd;
private readonly IntPtr ptr;
public DCUnbuffered(IntPtr ptr, IntPtr hWnd)
{
this.ptr = ptr;
this.hWnd = hWnd;
Graphics = Graphics.FromHdc(ptr);
}
public DCUnbuffered(IntPtr ptr)
{
this.ptr = ptr;
hWnd = IntPtr.Zero;
Graphics = Graphics.FromHdc(ptr);
}
public Graphics Graphics { get; }
public void Dispose()
{
Graphics.Dispose();
user32.ReleaseDC(hWnd, ptr);
}
}
}

10
W32/DCDrawer/IDCDrawer.cs Normal file
View File

@ -0,0 +1,10 @@
using System;
using System.Drawing;
namespace CC_Functions.W32.DCDrawer
{
public interface IDCDrawer : IDisposable
{
Graphics Graphics { get; }
}
}

52
W32/DeskMan.cs Normal file
View File

@ -0,0 +1,52 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using CC_Functions.W32.DCDrawer;
using CC_Functions.W32.Native;
using Microsoft.Win32;
namespace CC_Functions.W32
{
public static class DeskMan
{
public static Image Wallpaper
{
get
{
using (Bitmap bmpTemp =
new Bitmap(
$@"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\Microsoft\Windows\Themes\TranscodedWallpaper")
)
return (Image) bmpTemp.Clone();
}
set
{
string tempPath = Path.Combine(Path.GetTempPath(), "wallpaper.bmp");
value.Save(tempPath, ImageFormat.Bmp);
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true);
key.SetValue(@"WallpaperStyle", 2.ToString());
key.SetValue(@"TileWallpaper", 0.ToString());
user32.SystemParametersInfo(20, 0, tempPath, 0x01 | 0x02);
File.Delete(tempPath);
}
}
public static IDCDrawer CreateGraphics(bool buffered = false)
{
Wnd32 progman = Wnd32.FromMetadata("Progman");
IntPtr result = IntPtr.Zero;
user32.SendMessageTimeout(progman.HWnd, 0x052C, new IntPtr(0), IntPtr.Zero, 0x0, 1000, out result);
IntPtr workerW = IntPtr.Zero;
user32.EnumWindows((tophandle, topparamhandle) =>
{
IntPtr p = user32.FindWindowEx(tophandle, IntPtr.Zero, "SHELLDLL_DefView", IntPtr.Zero);
if (p != IntPtr.Zero) workerW = user32.FindWindowEx(IntPtr.Zero, tophandle, "WorkerW", IntPtr.Zero);
return true;
}, IntPtr.Zero);
IntPtr dc = user32.GetDCEx(workerW, IntPtr.Zero, 0x403);
if (dc == IntPtr.Zero) throw new Exception("Something went wrong when creatiing the Graphics object");
return buffered ? (IDCDrawer) new DCBuffered(dc) : new DCUnbuffered(dc);
}
}
}

View File

@ -0,0 +1,681 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CC_Functions.W32.Forms
{
public class DataGridViewNumericUpDownCell : DataGridViewTextBoxCell
{
// Default dimensions of the static rendering bitmap used for the painting of the non-edited cells
private const int DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapWidth = 100;
private const int DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapHeight = 22;
// Default value of the DecimalPlaces property
internal const int DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces = 0;
// Default value of the Increment property
internal const decimal DATAGRIDVIEWNUMERICUPDOWNCELL_defaultIncrement = decimal.One;
// Default value of the Maximum property
internal const decimal DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMaximum = (decimal) 100.0;
// Default value of the Minimum property
internal const decimal DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMinimum = decimal.Zero;
// Default value of the ThousandsSeparator property
internal const bool DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator = false;
// Used in TranslateAlignment function
private static readonly DataGridViewContentAlignment anyRight = DataGridViewContentAlignment.TopRight |
DataGridViewContentAlignment.MiddleRight |
DataGridViewContentAlignment.BottomRight;
private static readonly DataGridViewContentAlignment anyCenter = DataGridViewContentAlignment.TopCenter |
DataGridViewContentAlignment.MiddleCenter |
DataGridViewContentAlignment.BottomCenter;
// Type of this cell's editing control
private static readonly Type defaultEditType = typeof(DataGridViewNumericUpDownEditingControl);
// Type of this cell's value. The formatted value type is string, the same as the base class DataGridViewTextBoxCell
private static readonly Type defaultValueType = typeof(decimal);
// The bitmap used to paint the non-edited cells via a call to NumericUpDown.DrawToBitmap
[ThreadStatic] private static Bitmap renderingBitmap;
// The NumericUpDown control used to paint the non-edited cells via a call to NumericUpDown.DrawToBitmap
[ThreadStatic] private static NumericUpDown paintingNumericUpDown;
private int decimalPlaces; // Caches the value of the DecimalPlaces property
private decimal increment; // Caches the value of the Increment property
private decimal maximum; // Caches the value of the Maximum property
private decimal minimum; // Caches the value of the Minimum property
private bool thousandsSeparator; // Caches the value of the ThousandsSeparator property
/// <summary>
/// Constructor for the DataGridViewNumericUpDownCell cell type
/// </summary>
public DataGridViewNumericUpDownCell()
{
// Create a thread specific bitmap used for the painting of the non-edited cells
if (renderingBitmap == null)
renderingBitmap = new Bitmap(DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapWidth,
DATAGRIDVIEWNUMERICUPDOWNCELL_defaultRenderingBitmapHeight);
// Create a thread specific NumericUpDown control used for the painting of the non-edited cells
if (paintingNumericUpDown == null)
{
paintingNumericUpDown = new NumericUpDown();
// Some properties only need to be set once for the lifetime of the control:
paintingNumericUpDown.BorderStyle = BorderStyle.None;
paintingNumericUpDown.Maximum = decimal.MaxValue / 10;
paintingNumericUpDown.Minimum = decimal.MinValue / 10;
}
// Set the default values of the properties:
decimalPlaces = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces;
increment = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultIncrement;
minimum = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMinimum;
maximum = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMaximum;
thousandsSeparator = DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator;
}
/// <summary>
/// The DecimalPlaces property replicates the one from the NumericUpDown control
/// </summary>
[
DefaultValue(DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces)
]
public int DecimalPlaces
{
get => decimalPlaces;
set
{
if (value < 0 || value > 99)
throw new ArgumentOutOfRangeException(
"The DecimalPlaces property cannot be smaller than 0 or larger than 99.");
if (decimalPlaces != value)
{
SetDecimalPlaces(RowIndex, value);
OnCommonChange(); // Assure that the cell or column gets repainted and autosized if needed
}
}
}
/// <summary>
/// Returns the current DataGridView EditingControl as a DataGridViewNumericUpDownEditingControl control
/// </summary>
private DataGridViewNumericUpDownEditingControl EditingNumericUpDown =>
DataGridView.EditingControl as DataGridViewNumericUpDownEditingControl;
/// <summary>
/// Define the type of the cell's editing control
/// </summary>
public override Type EditType => defaultEditType; // the type is DataGridViewNumericUpDownEditingControl
/// <summary>
/// The Increment property replicates the one from the NumericUpDown control
/// </summary>
public decimal Increment
{
get => increment;
set
{
if (value < (decimal) 0.0)
throw new ArgumentOutOfRangeException("The Increment property cannot be smaller than 0.");
SetIncrement(RowIndex, value);
// No call to OnCommonChange is needed since the increment value does not affect the rendering of the cell.
}
}
/// <summary>
/// The Maximum property replicates the one from the NumericUpDown control
/// </summary>
public decimal Maximum
{
get => maximum;
set
{
if (maximum != value)
{
SetMaximum(RowIndex, value);
OnCommonChange();
}
}
}
/// <summary>
/// The Minimum property replicates the one from the NumericUpDown control
/// </summary>
public decimal Minimum
{
get => minimum;
set
{
if (minimum != value)
{
SetMinimum(RowIndex, value);
OnCommonChange();
}
}
}
/// <summary>
/// The ThousandsSeparator property replicates the one from the NumericUpDown control
/// </summary>
[
DefaultValue(DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator)
]
public bool ThousandsSeparator
{
get => thousandsSeparator;
set
{
if (thousandsSeparator != value)
{
SetThousandsSeparator(RowIndex, value);
OnCommonChange();
}
}
}
/// <summary>
/// Returns the type of the cell's Value property
/// </summary>
public override Type ValueType
{
get
{
Type valueType = base.ValueType;
if (valueType != null) return valueType;
return defaultValueType;
}
}
// Used in KeyEntersEditMode function
[DllImport("USER32.DLL", CharSet = CharSet.Auto)]
private static extern short VkKeyScan(char key);
/// <summary>
/// Clones a DataGridViewNumericUpDownCell cell, copies all the custom properties.
/// </summary>
public override object Clone()
{
DataGridViewNumericUpDownCell dataGridViewCell = base.Clone() as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
{
dataGridViewCell.DecimalPlaces = DecimalPlaces;
dataGridViewCell.Increment = Increment;
dataGridViewCell.Maximum = Maximum;
dataGridViewCell.Minimum = Minimum;
dataGridViewCell.ThousandsSeparator = ThousandsSeparator;
}
return dataGridViewCell;
}
/// <summary>
/// Returns the provided value constrained to be within the min and max.
/// </summary>
private decimal Constrain(decimal value)
{
Debug.Assert(minimum <= maximum);
if (value < minimum) value = minimum;
if (value > maximum) value = maximum;
return value;
}
/// <summary>
/// DetachEditingControl gets called by the DataGridView control when the editing session is ending
/// </summary>
[
EditorBrowsable(EditorBrowsableState.Advanced)
]
public override void DetachEditingControl()
{
DataGridView dataGridView = DataGridView;
if (dataGridView == null || dataGridView.EditingControl == null)
throw new InvalidOperationException("Cell is detached or its grid has no editing control.");
NumericUpDown numericUpDown = dataGridView.EditingControl as NumericUpDown;
if (numericUpDown != null)
{
// Editing controls get recycled. Indeed, when a DataGridViewNumericUpDownCell cell gets edited
// after another DataGridViewNumericUpDownCell cell, the same editing control gets reused for
// performance reasons (to avoid an unnecessary control destruction and creation).
// Here the undo buffer of the TextBox inside the NumericUpDown control gets cleared to avoid
// interferences between the editing sessions.
TextBox textBox = numericUpDown.Controls[1] as TextBox;
if (textBox != null) textBox.ClearUndo();
}
base.DetachEditingControl();
}
/// <summary>
/// Adjusts the location and size of the editing control given the alignment characteristics of the cell
/// </summary>
private Rectangle GetAdjustedEditingControlBounds(Rectangle editingControlBounds,
DataGridViewCellStyle cellStyle)
{
// Add a 1 pixel padding on the left and right of the editing control
editingControlBounds.X += 1;
editingControlBounds.Width = Math.Max(0, editingControlBounds.Width - 2);
// Adjust the vertical location of the editing control:
int preferredHeight = cellStyle.Font.Height + 3;
if (preferredHeight < editingControlBounds.Height)
switch (cellStyle.Alignment)
{
case DataGridViewContentAlignment.MiddleLeft:
case DataGridViewContentAlignment.MiddleCenter:
case DataGridViewContentAlignment.MiddleRight:
editingControlBounds.Y += (editingControlBounds.Height - preferredHeight) / 2;
break;
case DataGridViewContentAlignment.BottomLeft:
case DataGridViewContentAlignment.BottomCenter:
case DataGridViewContentAlignment.BottomRight:
editingControlBounds.Y += editingControlBounds.Height - preferredHeight;
break;
}
return editingControlBounds;
}
/// <summary>
/// Customized implementation of the GetErrorIconBounds function in order to draw the potential
/// error icon next to the up/down buttons and not on top of them.
/// </summary>
protected override Rectangle GetErrorIconBounds(Graphics graphics, DataGridViewCellStyle cellStyle,
int rowIndex)
{
const int ButtonsWidth = 16;
Rectangle errorIconBounds = base.GetErrorIconBounds(graphics, cellStyle, rowIndex);
if (DataGridView.RightToLeft == RightToLeft.Yes)
errorIconBounds.X = errorIconBounds.Left + ButtonsWidth;
else
errorIconBounds.X = errorIconBounds.Left - ButtonsWidth;
return errorIconBounds;
}
/// <summary>
/// Customized implementation of the GetFormattedValue function in order to include the decimal and thousand separator
/// characters in the formatted representation of the cell value.
/// </summary>
protected override object GetFormattedValue(object value,
int rowIndex,
ref DataGridViewCellStyle cellStyle,
TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts context)
{
// By default, the base implementation converts the Decimal 1234.5 into the string "1234.5"
object formattedValue = base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
string formattedNumber = formattedValue as string;
if (!string.IsNullOrEmpty(formattedNumber) && value != null)
{
decimal unformattedDecimal = Convert.ToDecimal(value);
decimal formattedDecimal = Convert.ToDecimal(formattedNumber);
if (unformattedDecimal == formattedDecimal)
// The base implementation of GetFormattedValue (which triggers the CellFormatting event) did nothing else than
// the typical 1234.5 to "1234.5" conversion. But depending on the values of ThousandsSeparator and DecimalPlaces,
// this may not be the actual string displayed. The real formatted value may be "1,234.500"
return formattedDecimal.ToString((ThousandsSeparator ? "N" : "F") + DecimalPlaces);
}
return formattedValue;
}
/// <summary>
/// Custom implementation of the GetPreferredSize function. This implementation uses the preferred size of the base
/// DataGridViewTextBoxCell cell and adds room for the up/down buttons.
/// </summary>
protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex,
Size constraintSize)
{
if (DataGridView == null) return new Size(-1, -1);
Size preferredSize = base.GetPreferredSize(graphics, cellStyle, rowIndex, constraintSize);
if (constraintSize.Width == 0)
{
const int ButtonsWidth = 16; // Account for the width of the up/down buttons.
const int ButtonMargin = 8; // Account for some blank pixels between the text and buttons.
preferredSize.Width += ButtonsWidth + ButtonMargin;
}
return preferredSize;
}
/// <summary>
/// Custom implementation of the InitializeEditingControl function. This function is called by the DataGridView control
/// at the beginning of an editing session. It makes sure that the properties of the NumericUpDown editing control are
/// set according to the cell properties.
/// </summary>
public override void InitializeEditingControl(int rowIndex, object initialFormattedValue,
DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
NumericUpDown numericUpDown = DataGridView.EditingControl as NumericUpDown;
if (numericUpDown != null)
{
numericUpDown.BorderStyle = BorderStyle.None;
numericUpDown.DecimalPlaces = DecimalPlaces;
numericUpDown.Increment = Increment;
numericUpDown.Maximum = Maximum;
numericUpDown.Minimum = Minimum;
numericUpDown.ThousandsSeparator = ThousandsSeparator;
string initialFormattedValueStr = initialFormattedValue as string;
if (initialFormattedValueStr == null)
numericUpDown.Text = string.Empty;
else
numericUpDown.Text = initialFormattedValueStr;
}
}
/// <summary>
/// Custom implementation of the KeyEntersEditMode function. This function is called by the DataGridView control
/// to decide whether a keystroke must start an editing session or not. In this case, a new session is started when
/// a digit or negative sign key is hit.
/// </summary>
public override bool KeyEntersEditMode(KeyEventArgs e)
{
NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
Keys negativeSignKey = Keys.None;
string negativeSignStr = numberFormatInfo.NegativeSign;
if (!string.IsNullOrEmpty(negativeSignStr) && negativeSignStr.Length == 1)
negativeSignKey = (Keys) VkKeyScan(negativeSignStr[0]);
if ((char.IsDigit((char) e.KeyCode) ||
e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9 ||
negativeSignKey == e.KeyCode ||
Keys.Subtract == e.KeyCode) &&
!e.Shift && !e.Alt && !e.Control)
return true;
return false;
}
/// <summary>
/// Called when a cell characteristic that affects its rendering and/or preferred size has changed.
/// This implementation only takes care of repainting the cells. The DataGridView's autosizing methods
/// also need to be called in cases where some grid elements autosize.
/// </summary>
private void OnCommonChange()
{
if (DataGridView != null && !DataGridView.IsDisposed && !DataGridView.Disposing)
{
if (RowIndex == -1)
// Invalidate and autosize column
DataGridView.InvalidateColumn(ColumnIndex);
// TODO: Add code to autosize the cell's column, the rows, the column headers
// and the row headers depending on their autosize settings.
// The DataGridView control does not expose a public method that takes care of this.
else
// The DataGridView control exposes a public method called UpdateCellValue
// that invalidates the cell so that it gets repainted and also triggers all
// the necessary autosizing: the cell's column and/or row, the column headers
// and the row headers are autosized depending on their autosize settings.
DataGridView.UpdateCellValue(ColumnIndex, RowIndex);
}
}
/// <summary>
/// Determines whether this cell, at the given row index, shows the grid's editing control or not.
/// The row index needs to be provided as a parameter because this cell may be shared among multiple rows.
/// </summary>
private bool OwnsEditingNumericUpDown(int rowIndex)
{
if (rowIndex == -1 || DataGridView == null) return false;
DataGridViewNumericUpDownEditingControl numericUpDownEditingControl =
DataGridView.EditingControl as DataGridViewNumericUpDownEditingControl;
return numericUpDownEditingControl != null && rowIndex ==
((IDataGridViewEditingControl) numericUpDownEditingControl).EditingControlRowIndex;
}
/// <summary>
/// Custom paints the cell. The base implementation of the DataGridViewTextBoxCell type is called first,
/// dropping the icon error and content foreground parts. Those two parts are painted by this custom implementation.
/// In this sample, the non-edited NumericUpDown control is painted by using a call to Control.DrawToBitmap. This is
/// an easy solution for painting controls but it's not necessarily the most performant. An alternative would be to
/// paint
/// the NumericUpDown control piece by piece (text and up/down buttons).
/// </summary>
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
DataGridViewElementStates cellState,
object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
if (DataGridView == null) return;
// First paint the borders and background of the cell.
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText,
cellStyle, advancedBorderStyle,
paintParts & ~(DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.ContentForeground));
Point ptCurrentCell = DataGridView.CurrentCellAddress;
bool cellCurrent = ptCurrentCell.X == ColumnIndex && ptCurrentCell.Y == rowIndex;
bool cellEdited = cellCurrent && DataGridView.EditingControl != null;
// If the cell is in editing mode, there is nothing else to paint
if (!cellEdited)
{
if (PartPainted(paintParts, DataGridViewPaintParts.ContentForeground))
{
// Paint a NumericUpDown control
// Take the borders into account
Rectangle borderWidths = BorderWidths(advancedBorderStyle);
Rectangle valBounds = cellBounds;
valBounds.Offset(borderWidths.X, borderWidths.Y);
valBounds.Width -= borderWidths.Right;
valBounds.Height -= borderWidths.Bottom;
// Also take the padding into account
if (cellStyle.Padding != Padding.Empty)
{
if (DataGridView.RightToLeft == RightToLeft.Yes)
valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top);
else
valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top);
valBounds.Width -= cellStyle.Padding.Horizontal;
valBounds.Height -= cellStyle.Padding.Vertical;
}
// Determine the NumericUpDown control location
valBounds = GetAdjustedEditingControlBounds(valBounds, cellStyle);
bool cellSelected = (cellState & DataGridViewElementStates.Selected) != 0;
if (renderingBitmap.Width < valBounds.Width ||
renderingBitmap.Height < valBounds.Height)
{
// The static bitmap is too small, a bigger one needs to be allocated.
renderingBitmap.Dispose();
renderingBitmap = new Bitmap(valBounds.Width, valBounds.Height);
}
// Make sure the NumericUpDown control is parented to a visible control
if (paintingNumericUpDown.Parent == null || !paintingNumericUpDown.Parent.Visible)
paintingNumericUpDown.Parent = DataGridView;
// Set all the relevant properties
paintingNumericUpDown.TextAlign = TranslateAlignment(cellStyle.Alignment);
paintingNumericUpDown.DecimalPlaces = DecimalPlaces;
paintingNumericUpDown.ThousandsSeparator = ThousandsSeparator;
paintingNumericUpDown.Font = cellStyle.Font;
paintingNumericUpDown.Width = valBounds.Width;
paintingNumericUpDown.Height = valBounds.Height;
paintingNumericUpDown.RightToLeft = DataGridView.RightToLeft;
paintingNumericUpDown.Location = new Point(0, -paintingNumericUpDown.Height - 100);
paintingNumericUpDown.Text = formattedValue as string;
Color backColor;
if (PartPainted(paintParts, DataGridViewPaintParts.SelectionBackground) && cellSelected)
backColor = cellStyle.SelectionBackColor;
else
backColor = cellStyle.BackColor;
if (PartPainted(paintParts, DataGridViewPaintParts.Background))
{
if (backColor.A < 255)
// The NumericUpDown control does not support transparent back colors
backColor = Color.FromArgb(255, backColor);
paintingNumericUpDown.BackColor = backColor;
}
// Finally paint the NumericUpDown control
Rectangle srcRect = new Rectangle(0, 0, valBounds.Width, valBounds.Height);
if (srcRect.Width > 0 && srcRect.Height > 0)
{
paintingNumericUpDown.DrawToBitmap(renderingBitmap, srcRect);
graphics.DrawImage(renderingBitmap, new Rectangle(valBounds.Location, valBounds.Size),
srcRect, GraphicsUnit.Pixel);
}
}
if (PartPainted(paintParts, DataGridViewPaintParts.ErrorIcon))
// Paint the potential error icon on top of the NumericUpDown control
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText,
cellStyle, advancedBorderStyle, DataGridViewPaintParts.ErrorIcon);
}
}
/// <summary>
/// Little utility function called by the Paint function to see if a particular part needs to be painted.
/// </summary>
private static bool PartPainted(DataGridViewPaintParts paintParts, DataGridViewPaintParts paintPart) =>
(paintParts & paintPart) != 0;
/// <summary>
/// Custom implementation of the PositionEditingControl method called by the DataGridView control when it
/// needs to relocate and/or resize the editing control.
/// </summary>
public override void PositionEditingControl(bool setLocation,
bool setSize,
Rectangle cellBounds,
Rectangle cellClip,
DataGridViewCellStyle cellStyle,
bool singleVerticalBorderAdded,
bool singleHorizontalBorderAdded,
bool isFirstDisplayedColumn,
bool isFirstDisplayedRow)
{
Rectangle editingControlBounds = PositionEditingPanel(cellBounds,
cellClip,
cellStyle,
singleVerticalBorderAdded,
singleHorizontalBorderAdded,
isFirstDisplayedColumn,
isFirstDisplayedRow);
editingControlBounds = GetAdjustedEditingControlBounds(editingControlBounds, cellStyle);
DataGridView.EditingControl.Location = new Point(editingControlBounds.X, editingControlBounds.Y);
DataGridView.EditingControl.Size = new Size(editingControlBounds.Width, editingControlBounds.Height);
}
/// <summary>
/// Utility function that sets a new value for the DecimalPlaces property of the cell. This function is used by
/// the cell and column DecimalPlaces property. The column uses this method instead of the DecimalPlaces
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
/// </summary>
internal void SetDecimalPlaces(int rowIndex, int value)
{
Debug.Assert(value >= 0 && value <= 99);
decimalPlaces = value;
if (OwnsEditingNumericUpDown(rowIndex)) EditingNumericUpDown.DecimalPlaces = value;
}
/// Utility function that sets a new value for the Increment property of the cell. This function is used by
/// the cell and column Increment property. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetIncrement(int rowIndex, decimal value)
{
Debug.Assert(value >= (decimal) 0.0);
increment = value;
if (OwnsEditingNumericUpDown(rowIndex)) EditingNumericUpDown.Increment = value;
}
/// Utility function that sets a new value for the Maximum property of the cell. This function is used by
/// the cell and column Maximum property. The column uses this method instead of the Maximum
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetMaximum(int rowIndex, decimal value)
{
maximum = value;
if (minimum > maximum) minimum = maximum;
object cellValue = GetValue(rowIndex);
if (cellValue != null)
{
decimal currentValue = Convert.ToDecimal(cellValue);
decimal constrainedValue = Constrain(currentValue);
if (constrainedValue != currentValue) SetValue(rowIndex, constrainedValue);
}
Debug.Assert(maximum == value);
if (OwnsEditingNumericUpDown(rowIndex)) EditingNumericUpDown.Maximum = value;
}
/// Utility function that sets a new value for the Minimum property of the cell. This function is used by
/// the cell and column Minimum property. The column uses this method instead of the Minimum
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetMinimum(int rowIndex, decimal value)
{
minimum = value;
if (minimum > maximum) maximum = value;
object cellValue = GetValue(rowIndex);
if (cellValue != null)
{
decimal currentValue = Convert.ToDecimal(cellValue);
decimal constrainedValue = Constrain(currentValue);
if (constrainedValue != currentValue) SetValue(rowIndex, constrainedValue);
}
Debug.Assert(minimum == value);
if (OwnsEditingNumericUpDown(rowIndex)) EditingNumericUpDown.Minimum = value;
}
/// Utility function that sets a new value for the ThousandsSeparator property of the cell. This function is used by
/// the cell and column ThousandsSeparator property. The column uses this method instead of the ThousandsSeparator
/// property for performance reasons. This way the column can invalidate the entire column at once instead of
/// invalidating each cell of the column individually. A row index needs to be provided as a parameter because
/// this cell may be shared among multiple rows.
internal void SetThousandsSeparator(int rowIndex, bool value)
{
thousandsSeparator = value;
if (OwnsEditingNumericUpDown(rowIndex)) EditingNumericUpDown.ThousandsSeparator = value;
}
/// <summary>
/// Returns a standard textual representation of the cell.
/// </summary>
public override string ToString() =>
$"DataGridViewNumericUpDownCell {{ ColumnIndex={ColumnIndex.ToString(CultureInfo.CurrentCulture)}, RowIndex={RowIndex.ToString(CultureInfo.CurrentCulture)} }}";
/// <summary>
/// Little utility function used by both the cell and column types to translate a DataGridViewContentAlignment value
/// into
/// a HorizontalAlignment value.
/// </summary>
internal static HorizontalAlignment TranslateAlignment(DataGridViewContentAlignment align)
{
if ((align & anyRight) != 0)
return HorizontalAlignment.Right;
if ((align & anyCenter) != 0)
return HorizontalAlignment.Center;
return HorizontalAlignment.Left;
}
}
}

View File

@ -0,0 +1,274 @@
using System;
using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
namespace CC_Functions.W32.Forms
{
/// <summary>
/// Custom column type dedicated to the DataGridViewNumericUpDownCell cell type.
/// </summary>
public class DataGridViewNumericUpDownColumn : DataGridViewColumn
{
/// <summary>
/// Constructor for the DataGridViewNumericUpDownColumn class.
/// </summary>
public DataGridViewNumericUpDownColumn() : base(new DataGridViewNumericUpDownCell())
{
}
/// <summary>
/// Represents the implicit cell that gets cloned when adding rows to the grid.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override DataGridViewCell CellTemplate
{
get => base.CellTemplate;
set
{
DataGridViewNumericUpDownCell dataGridViewNumericUpDownCell = value as DataGridViewNumericUpDownCell;
if (value != null && dataGridViewNumericUpDownCell == null)
throw new InvalidCastException(
"Value provided for CellTemplate must be of type DataGridViewNumericUpDownElements.DataGridViewNumericUpDownCell or derive from it.");
base.CellTemplate = value;
}
}
/// <summary>
/// Replicates the DecimalPlaces property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[Category("Appearance")]
[DefaultValue(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultDecimalPlaces)]
[Description("Indicates the number of decimal places to display.")]
public int DecimalPlaces
{
get
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
return NumericUpDownCellTemplate.DecimalPlaces;
}
set
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
// Update the template cell so that subsequent cloned cells use the new value.
NumericUpDownCellTemplate.DecimalPlaces = value;
if (DataGridView != null)
{
// Update all the existing DataGridViewNumericUpDownCell cells in the column accordingly.
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
// Be careful not to unshare rows unnecessarily.
// This could have severe performance repercussions.
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell =
dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null)
// Call the internal SetDecimalPlaces method instead of the property to avoid invalidation
// of each cell. The whole column is invalidated later in a single operation for better performance.
dataGridViewCell.SetDecimalPlaces(rowIndex, value);
}
DataGridView.InvalidateColumn(Index);
// TODO: Call the grid's autosizing methods to autosize the column, rows, column headers / row headers as needed.
}
}
}
/// <summary>
/// Replicates the Increment property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[Category("Data")]
[Description("Indicates the amount to increment or decrement on each button click.")]
public decimal Increment
{
get
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
return NumericUpDownCellTemplate.Increment;
}
set
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
NumericUpDownCellTemplate.Increment = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell =
dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null) dataGridViewCell.SetIncrement(rowIndex, value);
}
}
}
}
/// <summary>
/// Replicates the Maximum property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[Category("Data")]
[Description("Indicates the maximum value for the numeric up-down cells.")]
[RefreshProperties(RefreshProperties.All)]
public decimal Maximum
{
get
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
return NumericUpDownCellTemplate.Maximum;
}
set
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
NumericUpDownCellTemplate.Maximum = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell =
dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null) dataGridViewCell.SetMaximum(rowIndex, value);
}
DataGridView.InvalidateColumn(Index);
// TODO: This column and/or grid rows may need to be autosized depending on their
// autosize settings. Call the autosizing methods to autosize the column, rows,
// column headers / row headers as needed.
}
}
}
/// <summary>
/// Replicates the Minimum property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[Category("Data")]
[Description("Indicates the minimum value for the numeric up-down cells.")]
[RefreshProperties(RefreshProperties.All)]
public decimal Minimum
{
get
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
return NumericUpDownCellTemplate.Minimum;
}
set
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
NumericUpDownCellTemplate.Minimum = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell =
dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null) dataGridViewCell.SetMinimum(rowIndex, value);
}
DataGridView.InvalidateColumn(Index);
// TODO: This column and/or grid rows may need to be autosized depending on their
// autosize settings. Call the autosizing methods to autosize the column, rows,
// column headers / row headers as needed.
}
}
}
/// <summary>
/// Replicates the ThousandsSeparator property of the DataGridViewNumericUpDownCell cell type.
/// </summary>
[Category("Data")]
[DefaultValue(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultThousandsSeparator)]
[Description("Indicates whether the thousands separator will be inserted between every three decimal digits.")]
public bool ThousandsSeparator
{
get
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
return NumericUpDownCellTemplate.ThousandsSeparator;
}
set
{
if (NumericUpDownCellTemplate == null)
throw new InvalidOperationException(
"Operation cannot be completed because this DataGridViewColumn does not have a CellTemplate.");
NumericUpDownCellTemplate.ThousandsSeparator = value;
if (DataGridView != null)
{
DataGridViewRowCollection dataGridViewRows = DataGridView.Rows;
int rowCount = dataGridViewRows.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataGridViewRow dataGridViewRow = dataGridViewRows.SharedRow(rowIndex);
DataGridViewNumericUpDownCell dataGridViewCell =
dataGridViewRow.Cells[Index] as DataGridViewNumericUpDownCell;
if (dataGridViewCell != null) dataGridViewCell.SetThousandsSeparator(rowIndex, value);
}
DataGridView.InvalidateColumn(Index);
// TODO: This column and/or grid rows may need to be autosized depending on their
// autosize settings. Call the autosizing methods to autosize the column, rows,
// column headers / row headers as needed.
}
}
}
/// <summary>
/// Small utility function that returns the template cell as a DataGridViewNumericUpDownCell
/// </summary>
private DataGridViewNumericUpDownCell NumericUpDownCellTemplate => (DataGridViewNumericUpDownCell) CellTemplate;
/// Indicates whether the Increment property should be persisted.
private bool ShouldSerializeIncrement() =>
!Increment.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultIncrement);
/// Indicates whether the Maximum property should be persisted.
private bool ShouldSerializeMaximum() =>
!Maximum.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMaximum);
/// Indicates whether the Maximum property should be persisted.
private bool ShouldSerializeMinimum() =>
!Minimum.Equals(DataGridViewNumericUpDownCell.DATAGRIDVIEWNUMERICUPDOWNCELL_defaultMinimum);
/// <summary>
/// Returns a standard compact string representation of the column.
/// </summary>
public override string ToString()
{
StringBuilder sb = new StringBuilder(100);
sb.Append("DataGridViewNumericUpDownColumn { Name=");
sb.Append(Name);
sb.Append(", Index=");
sb.Append(Index.ToString(CultureInfo.CurrentCulture));
sb.Append(" }");
return sb.ToString();
}
}
}

View File

@ -0,0 +1,284 @@
using System;
using System.Drawing;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CC_Functions.W32.Forms
{
/// <summary>
/// Defines the editing control for the DataGridViewNumericUpDownCell custom cell type.
/// </summary>
internal class DataGridViewNumericUpDownEditingControl : NumericUpDown, IDataGridViewEditingControl
{
// The grid that owns this editing control
private DataGridView dataGridView;
// Stores the row index in which the editing control resides
// Stores whether the editing control's value has changed or not
private bool valueChanged;
/// <summary>
/// Constructor of the editing control class
/// </summary>
// The editing control must not be part of the tabbing loop
public DataGridViewNumericUpDownEditingControl() => TabStop = false;
// Beginning of the IDataGridViewEditingControl interface implementation
/// <summary>
/// Property which caches the grid that uses this editing control
/// </summary>
public virtual DataGridView EditingControlDataGridView
{
get => dataGridView;
set => dataGridView = value;
}
/// <summary>
/// Property which represents the current formatted value of the editing control
/// </summary>
public virtual object EditingControlFormattedValue
{
get => GetEditingControlFormattedValue(DataGridViewDataErrorContexts.Formatting);
set => Text = (string) value;
}
/// <summary>
/// Property which represents the row in which the editing control resides
/// </summary>
public virtual int EditingControlRowIndex { get; set; }
/// <summary>
/// Property which indicates whether the value of the editing control has changed or not
/// </summary>
public virtual bool EditingControlValueChanged
{
get => valueChanged;
set => valueChanged = value;
}
/// <summary>
/// Property which determines which cursor must be used for the editing panel,
/// i.e. the parent of the editing control.
/// </summary>
public virtual Cursor EditingPanelCursor => Cursors.Default;
/// <summary>
/// Property which indicates whether the editing control needs to be repositioned
/// when its value changes.
/// </summary>
public virtual bool RepositionEditingControlOnValueChange => false;
/// <summary>
/// Method called by the grid before the editing control is shown so it can adapt to the
/// provided cell style.
/// </summary>
public virtual void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
{
Font = dataGridViewCellStyle.Font;
if (dataGridViewCellStyle.BackColor.A < 255)
{
// The NumericUpDown control does not support transparent back colors
Color opaqueBackColor = Color.FromArgb(255, dataGridViewCellStyle.BackColor);
BackColor = opaqueBackColor;
dataGridView.EditingPanel.BackColor = opaqueBackColor;
}
else
BackColor = dataGridViewCellStyle.BackColor;
ForeColor = dataGridViewCellStyle.ForeColor;
TextAlign = DataGridViewNumericUpDownCell.TranslateAlignment(dataGridViewCellStyle.Alignment);
}
/// <summary>
/// Method called by the grid on keystrokes to determine if the editing control is
/// interested in the key or not.
/// </summary>
public virtual bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Right:
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
// If the end of the selection is at the end of the string,
// let the DataGridView treat the key message
if (RightToLeft == RightToLeft.No &&
!(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length) ||
RightToLeft == RightToLeft.Yes &&
!(textBox.SelectionLength == 0 && textBox.SelectionStart == 0))
return true;
break;
}
case Keys.Left:
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
// If the end of the selection is at the begining of the string
// or if the entire text is selected and we did not start editing,
// send this character to the dataGridView, else process the key message
if (RightToLeft == RightToLeft.No &&
!(textBox.SelectionLength == 0 && textBox.SelectionStart == 0) ||
RightToLeft == RightToLeft.Yes &&
!(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length))
return true;
break;
}
case Keys.Down:
// If the current value hasn't reached its minimum yet, handle the key. Otherwise let
// the grid handle it.
if (Value > Minimum) return true;
break;
case Keys.Up:
// If the current value hasn't reached its maximum yet, handle the key. Otherwise let
// the grid handle it.
if (Value < Maximum) return true;
break;
case Keys.Home:
case Keys.End:
{
// Let the grid handle the key if the entire text is selected.
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
if (textBox.SelectionLength != textBox.Text.Length)
return true;
break;
}
case Keys.Delete:
{
// Let the grid handle the key if the carret is at the end of the text.
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
if (textBox.SelectionLength > 0 ||
textBox.SelectionStart < textBox.Text.Length)
return true;
break;
}
}
return !dataGridViewWantsInputKey;
}
/// <summary>
/// Returns the current value of the editing control.
/// </summary>
public virtual object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
{
bool userEdit = UserEdit;
try
{
// Prevent the Value from being set to Maximum or Minimum when the cell is being painted.
UserEdit = (context & DataGridViewDataErrorContexts.Display) == 0;
return Value.ToString((ThousandsSeparator ? "N" : "F") + DecimalPlaces);
}
finally
{
UserEdit = userEdit;
}
}
/// <summary>
/// Called by the grid to give the editing control a chance to prepare itself for
/// the editing session.
/// </summary>
public virtual void PrepareEditingControlForEdit(bool selectAll)
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
if (selectAll)
textBox.SelectAll();
else
// Do not select all the text, but
// position the caret at the end of the text
textBox.SelectionStart = textBox.Text.Length;
}
}
// Needed to forward keyboard messages to the child TextBox control.
[DllImport("USER32.DLL", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
// End of the IDataGridViewEditingControl interface implementation
/// <summary>
/// Small utility function that updates the local dirty state and
/// notifies the grid of the value change.
/// </summary>
private void NotifyDataGridViewOfValueChange()
{
if (!valueChanged)
{
valueChanged = true;
dataGridView.NotifyCurrentCellDirty(true);
}
}
/// <summary>
/// Listen to the KeyPress notification to know when the value changed, and
/// notify the grid of the change.
/// </summary>
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
// The value changes when a digit, the decimal separator, the group separator or
// the negative sign is pressed.
bool notifyValueChange = false;
if (char.IsDigit(e.KeyChar))
notifyValueChange = true;
else
{
NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
string decimalSeparatorStr = numberFormatInfo.NumberDecimalSeparator;
string groupSeparatorStr = numberFormatInfo.NumberGroupSeparator;
string negativeSignStr = numberFormatInfo.NegativeSign;
if (!string.IsNullOrEmpty(decimalSeparatorStr) && decimalSeparatorStr.Length == 1)
notifyValueChange = decimalSeparatorStr[0] == e.KeyChar;
if (!notifyValueChange && !string.IsNullOrEmpty(groupSeparatorStr) && groupSeparatorStr.Length == 1)
notifyValueChange = groupSeparatorStr[0] == e.KeyChar;
if (!notifyValueChange && !string.IsNullOrEmpty(negativeSignStr) && negativeSignStr.Length == 1)
notifyValueChange = negativeSignStr[0] == e.KeyChar;
}
if (notifyValueChange)
// Let the DataGridView know about the value change
NotifyDataGridViewOfValueChange();
}
/// <summary>
/// Listen to the ValueChanged notification to forward the change to the grid.
/// </summary>
protected override void OnValueChanged(EventArgs e)
{
base.OnValueChanged(e);
if (Focused)
// Let the DataGridView know about the value change
NotifyDataGridViewOfValueChange();
}
/// <summary>
/// A few keyboard messages need to be forwarded to the inner textbox of the
/// NumericUpDown control so that the first character pressed appears in it.
/// </summary>
protected override bool ProcessKeyEventArgs(ref Message m)
{
TextBox textBox = Controls[1] as TextBox;
if (textBox != null)
{
SendMessage(textBox.Handle, m.Msg, m.WParam, m.LParam);
return true;
}
return base.ProcessKeyEventArgs(ref m);
}
}
}

92
W32/Forms/Extensions.cs Normal file
View File

@ -0,0 +1,92 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Windows.Forms;
namespace CC_Functions.W32.Forms
{
public delegate void SetPropertyDelegate<TCtl, TProp>(TCtl control, Expression<Func<TCtl, TProp>> propexpr,
TProp value) where TCtl : Control;
public delegate TProp GetPropertyDelegate<TCtl, TProp>(TCtl control, Expression<Func<TProp>> propexpr)
where TCtl : Control;
public delegate void InvokeActionDelegate<TCtl>(TCtl control, Delegate dlg, params object[] args)
where TCtl : Control;
public delegate TResult InvokeFuncDelegate<TCtl, TResult>(TCtl control, Delegate dlg, params object[] args)
where TCtl : Control;
public static class Extensions
{
public static void SetProperty<TCtl, TProp>(this TCtl control, Expression<Func<TCtl, TProp>> propexpr,
TProp value) where TCtl : Control
{
if (control == null)
throw new ArgumentNullException(nameof(control));
if (propexpr == null)
throw new ArgumentNullException(nameof(propexpr));
if (control.InvokeRequired)
{
control.Invoke(new SetPropertyDelegate<TCtl, TProp>(SetProperty), control, propexpr, value);
return;
}
MemberExpression propexprm = propexpr.Body as MemberExpression;
if (propexprm == null)
throw new ArgumentException("Invalid member expression.", nameof(propexpr));
PropertyInfo prop = propexprm.Member as PropertyInfo;
if (prop == null)
throw new ArgumentException("Invalid property supplied.", nameof(propexpr));
prop.SetValue(control, value);
}
public static TProp GetProperty<TCtl, TProp>(this TCtl control, Expression<Func<TProp>> propexpr)
where TCtl : Control
{
if (control == null)
throw new ArgumentNullException(nameof(control));
if (propexpr == null)
throw new ArgumentNullException(nameof(propexpr));
if (control.InvokeRequired)
return (TProp) control.Invoke(new GetPropertyDelegate<TCtl, TProp>(GetProperty), control, propexpr);
MemberExpression propexprm = propexpr.Body as MemberExpression;
if (propexprm == null)
throw new ArgumentException("Invalid member expression.", nameof(propexpr));
PropertyInfo prop = propexprm.Member as PropertyInfo;
if (prop == null)
throw new ArgumentException("Invalid property supplied.", nameof(propexpr));
return (TProp) prop.GetValue(control);
}
public static void InvokeAction<TCtl>(this TCtl control, Delegate dlg, params object[] args)
where TCtl : Control
{
if (control == null)
throw new ArgumentNullException(nameof(control));
if (dlg == null)
throw new ArgumentNullException(nameof(dlg));
if (control.InvokeRequired)
{
control.Invoke(new InvokeActionDelegate<TCtl>(InvokeAction), control, dlg, args);
return;
}
dlg.DynamicInvoke(args);
}
public static TResult InvokeFunc<TCtl, TResult>(this TCtl control, Delegate dlg, params object[] args)
where TCtl : Control
{
if (control == null)
throw new ArgumentNullException(nameof(control));
if (dlg == null)
throw new ArgumentNullException(nameof(dlg));
return control.InvokeRequired
? (TResult) control.Invoke(new InvokeFuncDelegate<TCtl, TResult>(InvokeFunc<TCtl, TResult>), control,
dlg, args)
: (TResult) dlg.DynamicInvoke(args);
}
}
}

View File

@ -0,0 +1,153 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Timer = System.Timers.Timer;
namespace CC_Functions.W32.Forms
{
/// <summary>
/// Animated control similar to update screens in Windows 8 and 10
/// </summary>
public sealed class RotatingIndicator : Control
{
private const double IndicatorOffset = Math.PI / 16;
private const int MaximumIndicators = 6;
private const int SizeFactor = 20;
private const double StartAt = 2 * Math.PI / 3;
private const double TimerInterval = 100.0;
private readonly Indicator[] indicators = new Indicator[MaximumIndicators];
private readonly Timer timer;
private int indicatorCenterRadius;
private int indicatorDiameter;
/// <summary>
/// Instantiates the control
/// </summary>
public RotatingIndicator()
{
for (int i = 0; i < 6; i++)
indicators[i] = new Indicator(StartAt + i * IndicatorOffset);
SetStyle(
ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
ControlStyles.SupportsTransparentBackColor, true);
UpdateStyles();
ForeColorChanged += (sender, e) => Invalidate();
SizeChanged += (sender, e) =>
{
int indicatorRadius = (int) Math.Round(Height / (double) SizeFactor);
indicatorDiameter = 2 * indicatorRadius;
Height = SizeFactor * indicatorRadius;
Width = Height;
int outerRadius = Height / 2;
int innerRadius = outerRadius - indicatorDiameter;
indicatorCenterRadius = innerRadius + indicatorRadius;
Invalidate();
};
OnSizeChanged(null);
timer = new Timer();
timer.Elapsed += (sender, e) =>
{
try
{
if (InvokeRequired)
Invoke((Action) Refresh);
else Refresh();
}
catch
{
// ignored
}
};
timer.Interval = TimerInterval;
timer.Enabled = true;
}
/// <summary>
/// Start/stops indicator animation
/// </summary>
[Category("Appearance")]
[Description("Start/stops indicator animation")]
[DefaultValue(true)]
[Bindable(true)]
public bool Animate
{
get => timer.Enabled;
set => timer.Enabled = value;
}
/// <summary>
/// Specifies indicator rotational refresh
/// </summary>
[Category("Appearance")]
[Description("Specifies indicator rotational refresh")]
[DefaultValue(200)]
[Bindable(true)]
public double RefreshRate
{
get => timer.Interval;
set
{
timer.Interval = Math.Max(Math.Min(value, 200), 10);
Invalidate();
}
}
/// <summary>
/// Disposes used objects and the control itself
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (disposing) timer.Dispose();
base.Dispose(disposing);
}
/// <summary>
/// Paints the control and cycles the animation
/// </summary>
/// <param name="e">Arguments specifying the painting target</param>
protected override void OnPaint(PaintEventArgs e)
{
GraphicsContainer state = e.Graphics.BeginContainer();
e.Graphics.TranslateTransform(-Left, -Top);
Rectangle clip = e.ClipRectangle;
clip.Offset(Left, Top);
PaintEventArgs pea = new PaintEventArgs(e.Graphics, clip);
InvokePaintBackground(Parent, pea);
InvokePaint(Parent, pea);
e.Graphics.EndContainer(state);
e.Graphics.Clear(BackColor);
Brush brush = new SolidBrush(ForeColor);
for (int i = MaximumIndicators - 1; i >= 0; i--)
{
double degrees = indicators[i].Radians;
if (degrees < 0.0)
degrees += 2 * Math.PI;
int dx = (int) Math.Round(indicatorCenterRadius * Math.Cos(degrees)) + indicatorCenterRadius;
int dy = indicatorCenterRadius - (int) Math.Round(indicatorCenterRadius * Math.Sin(degrees));
e.Graphics.FillEllipse(brush,
new Rectangle(new Point(dx, dy), new Size(indicatorDiameter, indicatorDiameter)));
degrees -= indicators[i].Speed * IndicatorOffset;
if (indicators[i].Speed > 1.0) indicators[i].Speed += 0.25;
if (degrees < 0.0) indicators[i].Speed = 1.25;
else if (degrees < StartAt) indicators[i].Speed = 1.0;
indicators[i].Radians = degrees;
}
brush.Dispose();
}
}
internal struct Indicator
{
public Indicator(double radians)
{
Radians = radians;
Speed = 1.0;
}
public double Radians { get; set; }
public double Speed { get; set; }
}
}

61
W32/Forms/SelectBox.Designer.cs generated Normal file
View File

@ -0,0 +1,61 @@
namespace CC_Functions.W32.Forms
{
partial class SelectBox<T>
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.listBox1 = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// listBox1
//
this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(0, 0);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(433, 145);
this.listBox1.TabIndex = 0;
this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
//
// SelectBox
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(433, 145);
this.Controls.Add(this.listBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "SelectBox";
this.Text = "SelectBox";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListBox listBox1;
}
}

34
W32/Forms/SelectBox.cs Normal file
View File

@ -0,0 +1,34 @@
using System;
using System.Linq;
using System.Windows.Forms;
namespace CC_Functions.W32.Forms
{
internal partial class SelectBox<T> : Form
{
public T result;
public SelectBox(T[] Options, string title = "")
{
InitializeComponent();
Text = title;
listBox1.Items.AddRange(Options.Select(s => (object) s).ToArray());
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
result = (T) listBox1.SelectedItem;
DialogResult = DialogResult.OK;
Close();
}
}
public static class SelectBox
{
public static T Show<T>(T[] Options, string title = "")
{
SelectBox<T> sb = new SelectBox<T>(Options, title);
return sb.ShowDialog() == DialogResult.OK ? sb.result : default;
}
}
}

17
W32/GenericExtensions.cs Normal file
View File

@ -0,0 +1,17 @@
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace CC_Functions.W32
{
public static class GenericExtensions
{
public static Wnd32 GetWindow(this IntPtr handle) => Wnd32.FromHandle(handle);
public static Wnd32 GetMainWindow(this Process handle) => Wnd32.GetProcessMain(handle);
public static Wnd32 GetWnd32(this Form frm) => Wnd32.FromForm(frm);
public static bool IsDown(this Keys key) => KeyboardReader.IsKeyDown(key);
public static Privileges.SecurityEntity GetEntity(this Privileges.SecurityEntity2 entity) =>
Privileges.EntityToEntity(entity);
}
}

View File

@ -1,187 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;
namespace CC_Functions.W32
{
public class KeyboardHookEventArgs : EventArgs
{
public KeyboardHookEventArgs(Keys key)
{
Key = key;
}
public Keys Key { get; }
public override string ToString() => Key.ToString();
}
public class KeyboardHook : IDisposable
{
public void Dispose()
{
instances.Remove(this);
if (instances.Count == 0)
UnhookWindowsHookEx(_hookID);
}
private static List<KeyboardHook> instances = new List<KeyboardHook>();
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public delegate void keyPress(KeyboardHookEventArgs _args);
public event keyPress OnKeyPress;
public KeyboardHook()
{
if (instances.Count == 0)
_hookID = SetHook(_proc);
instances.Add(this);
}
private IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
for (int i = 0; i < instances.Count; i++)
{
instances[i].OnKeyPress?.Invoke(new KeyboardHookEventArgs((Keys)vkCode));
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
public class MouseHookEventArgs : EventArgs {
public MouseHookEventArgs(Point point, MouseHook.MouseMessages message)
{
Point = point;
Message = message;
}
public Point Point { get; }
public MouseHook.MouseMessages Message { get; }
public override string ToString()
{
return Message.ToString() + "; " + Point.ToString();
}
}
public class MouseHook : IDisposable
{
public void Dispose()
{
instances.Remove(this);
if (instances.Count == 0)
UnhookWindowsHookEx(_hookID);
}
private static List<MouseHook> instances = new List<MouseHook>();
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public delegate void mouseEvent(MouseHookEventArgs _args);
public event mouseEvent OnMouse;
public MouseHook()
{
if (instances.Count == 0)
_hookID = SetHook(_proc);
instances.Add(this);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
for (int i = 0; i < instances.Count; i++)
{
instances[i].OnMouse?.Invoke(new MouseHookEventArgs(new Point(hookStruct.pt.x, hookStruct.pt.y), (MouseMessages)wParam));
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
public enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}

56
W32/Hooks/KeyboardHook.cs Normal file
View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using CC_Functions.W32.Native;
namespace CC_Functions.W32.Hooks
{
public sealed class KeyboardHook : IDisposable
{
public delegate void KeyPress(KeyboardHookEventArgs args);
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static readonly List<KeyboardHook> Instances = new List<KeyboardHook>();
private static readonly user32.LowLevelProc Proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public KeyboardHook()
{
if (Instances.Count == 0)
_hookID = SetHook(Proc);
Instances.Add(this);
}
public void Dispose()
{
Instances.Remove(this);
if (Instances.Count == 0)
user32.UnhookWindowsHookEx(_hookID);
}
public event KeyPress? OnKeyPress;
private IntPtr SetHook(user32.LowLevelProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
return user32.SetWindowsHookEx(WH_KEYBOARD_LL, proc, kernel32.GetModuleHandle(curModule.ModuleName), 0);
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr) WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
for (int i = 0; i < Instances.Count; i++)
Instances[i].OnKeyPress?.Invoke(new KeyboardHookEventArgs((Keys) vkCode));
}
return user32.CallNextHookEx(_hookID, nCode, wParam, lParam);
}
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Windows.Forms;
namespace CC_Functions.W32.Hooks
{
public sealed class KeyboardHookEventArgs : EventArgs
{
public KeyboardHookEventArgs(Keys key) => Key = key;
public Keys Key { get; }
public override string ToString() => Key.ToString();
}
}

83
W32/Hooks/MouseHook.cs Normal file
View File

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using CC_Functions.W32.Native;
namespace CC_Functions.W32.Hooks
{
public sealed class MouseHook : IDisposable
{
public delegate void MouseEvent(MouseHookEventArgs args);
public enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
private const int WH_MOUSE_LL = 14;
private static readonly List<MouseHook> Instances = new List<MouseHook>();
private static readonly user32.LowLevelProc Proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public MouseHook()
{
if (Instances.Count == 0)
_hookID = SetHook(Proc);
Instances.Add(this);
}
public void Dispose()
{
Instances.Remove(this);
if (Instances.Count == 0)
user32.UnhookWindowsHookEx(_hookID);
}
public event MouseEvent? OnMouse;
private static IntPtr SetHook(user32.LowLevelProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
return user32.SetWindowsHookEx(WH_MOUSE_LL, proc, kernel32.GetModuleHandle(curModule.ModuleName), 0);
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
for (int i = 0; i < Instances.Count; i++)
Instances[i].OnMouse?.Invoke(new MouseHookEventArgs(new Point(hookStruct.pt.x, hookStruct.pt.y),
(MouseMessages) wParam));
}
return user32.CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public readonly int x;
public readonly int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public readonly POINT pt;
public readonly uint mouseData;
public readonly uint flags;
public readonly uint time;
public readonly IntPtr dwExtraInfo;
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Drawing;
namespace CC_Functions.W32.Hooks
{
public class MouseHookEventArgs : EventArgs
{
public MouseHookEventArgs(Point point, MouseHook.MouseMessages message)
{
Point = point;
Message = message;
}
public Point Point { get; }
public MouseHook.MouseMessages Message { get; }
public override string ToString() => $"{Message}; {Point}";
}
}

19
W32/KeyboardReader.cs Normal file
View File

@ -0,0 +1,19 @@
using System.Windows.Forms;
using CC_Functions.W32.Native;
namespace CC_Functions.W32
{
public static class KeyboardReader
{
public static bool IsKeyDown(Keys key)
{
int state = 0;
short retVal = user32.GetKeyState((int) key);
if ((retVal & 0x8000) == 0x8000)
state |= 1;
if ((retVal & 1) == 1)
state |= 2;
return (state & 1) == 1;
}
}
}

35
W32/Mouse.cs Normal file
View File

@ -0,0 +1,35 @@
using System.Drawing;
using System.Windows.Forms;
using CC_Functions.W32.Native;
namespace CC_Functions.W32
{
/// <summary>
/// Functions for manipulating the mouse
/// </summary>
public static class Mouse
{
private const int MouseEventFLeftDown = 0x02;
private const int MouseEventFLeftUp = 0x04;
private const int MouseEventFRightDown = 0x08;
private const int MouseEventFRightUp = 0x10;
/// <summary>
/// Emulates a click at the cursors position
/// </summary>
/// <param name="right">Set to true to perform right-clicks instead of left-clicks</param>
public static void Click(bool right = false) => Click(Cursor.Position, right);
/// <summary>
/// Emulates a click at the specified position
/// </summary>
/// <param name="location">The position to perform the click at</param>
/// <param name="right">Set to true to perform right-clicks instead of left-clicks</param>
public static void Click(Point location, bool right = false) =>
user32.mouse_event(
(uint) (right
? MouseEventFRightDown | MouseEventFRightUp
: MouseEventFLeftDown | MouseEventFLeftUp), (uint) location.X,
(uint) location.Y, 0, 0);
}
}

13
W32/Native/RECT.cs Normal file
View File

@ -0,0 +1,13 @@
using System.Runtime.InteropServices;
namespace CC_Functions.W32.Native
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left, Top, Right, Bottom;
public int Height => Bottom - Top;
public int Width => Right - Left;
}
}

25
W32/Native/advapi32.cs Normal file
View File

@ -0,0 +1,25 @@
using System;
using System.Runtime.InteropServices;
namespace CC_Functions.W32.Native
{
internal static class advapi32
{
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LookupPrivilegeValue(string lpsystemname, string lpname,
[MarshalAs(UnmanagedType.Struct)] ref Privileges.LUID lpLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AdjustTokenPrivileges(IntPtr tokenhandle,
[MarshalAs(UnmanagedType.Bool)] bool disableAllPrivileges,
[MarshalAs(UnmanagedType.Struct)] ref Privileges.TOKEN_PRIVILEGES newstate, uint bufferlength,
IntPtr previousState, IntPtr returnlength);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccesss,
out IntPtr tokenHandle);
}
}

27
W32/Native/gdi32.cs Normal file
View File

@ -0,0 +1,27 @@
using System;
using System.Runtime.InteropServices;
namespace CC_Functions.W32.Native
{
internal static class gdi32
{
[DllImport("gdi32.dll", EntryPoint = "SelectObject")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
[DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
public static extern IntPtr DeleteDC(IntPtr hDc);
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
public static extern IntPtr DeleteObject(IntPtr hDc);
[DllImport("gdi32.dll", EntryPoint = "BitBlt")]
public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource,
int xSrc, int ySrc, int RasterOp);
}
}

37
W32/Native/kernel32.cs Normal file
View File

@ -0,0 +1,37 @@
using System;
using System.Runtime.InteropServices;
namespace CC_Functions.W32.Native
{
internal static class kernel32
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetSystemTime(ref SYSTEMTIME st);
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
}
}
}

22
W32/Native/ntdll.cs Normal file
View File

@ -0,0 +1,22 @@
using System;
using System.Runtime.InteropServices;
namespace CC_Functions.W32.Native
{
internal static class ntdll
{
[DllImport("ntdll.dll", SetLastError = true)]
public static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege,
out bool PreviousValue);
[DllImport("ntdll.dll")]
public static extern uint NtRaiseHardError(
uint ErrorStatus,
uint NumberOfParameters,
uint UnicodeStringParameterMask,
IntPtr Parameters,
uint ValidResponseOption,
out uint Response
);
}
}

11
W32/Native/shell32.cs Normal file
View File

@ -0,0 +1,11 @@
using System;
using System.Runtime.InteropServices;
namespace CC_Functions.W32.Native
{
internal static class shell32
{
[DllImport("Shell32.dll")]
public static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
}
}

142
W32/Native/user32.cs Normal file
View File

@ -0,0 +1,142 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace CC_Functions.W32.Native
{
internal static class user32
{
public delegate bool EnumDelegate(IntPtr hWnd, int lParam);
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr lParam);
public delegate IntPtr LowLevelProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ExitWindowsEx(Power.ExitWindows uFlags, Power.ShutdownReason dwReason);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern short GetKeyState(int keyCode);
[DllImport("user32.dll", EntryPoint = "GetDC")]
public static extern IntPtr GetDC(IntPtr ptr);
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", EntryPoint = "ReleaseDC")]
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelProc lpfn, IntPtr hMod,
uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern long GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(int xPoint, int yPoint);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetWindowTextW(IntPtr hWnd, string lpString);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowEnabled(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DestroyWindow(IntPtr hwnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy,
uint uFlags);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall,
ExactSpelling = true, SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", ExactSpelling = false, CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction,
IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
[DllImport("user32.dll")]
public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip, uint flags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumDelegate lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className,
IntPtr windowTitle);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam,
uint flags, uint timeout, out IntPtr result);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);
}
}

View File

@ -1,28 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using CC_Functions.W32.Native;
using static CC_Functions.W32.Privileges;
namespace CC_Functions.W32
{
public static class Power
{
[DllImport("ntdll.dll", SetLastError = true)]
public static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue);
[DllImport("ntdll.dll")]
private static extern uint NtRaiseHardError(
uint ErrorStatus,
uint NumberOfParameters,
uint UnicodeStringParameterMask,
IntPtr Parameters,
uint ValidResponseOption,
out uint Response
);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);
[Flags]
public enum ExitWindows : uint
{
// ONE of the following five:
LogOff = 0x00,
ShutDown = 0x01,
Reboot = 0x02,
PowerOff = 0x08,
RestartApps = 0x40,
// plus AT MOST ONE of the following two:
Force = 0x04,
ForceIfHung = 0x10
}
[Flags]
public enum ShutdownMod : uint
{
None = 0x00,
Force = 0x04,
ForceIfHung = 0x10
}
[Flags]
public enum ShutdownMode : uint
{
LogOff = 0x00,
ShutDown = 0x01,
Reboot = 0x02,
PowerOff = 0x08,
RestartApps = 0x40,
BSoD = 0x29a
}
[Flags]
public enum ShutdownReason : uint
{
@ -65,115 +84,20 @@ namespace CC_Functions.W32
FlagUserDefined = 0x40000000,
FlagPlanned = 0x80000000
}
[Flags]
public enum ExitWindows : uint
{
// ONE of the following five:
LogOff = 0x00,
ShutDown = 0x01,
Reboot = 0x02,
PowerOff = 0x08,
RestartApps = 0x40,
// plus AT MOST ONE of the following two:
Force = 0x04,
ForceIfHung = 0x10,
}
[Flags]
public enum ShutdownMode : uint
{
LogOff = 0x00,
ShutDown = 0x01,
Reboot = 0x02,
PowerOff = 0x08,
RestartApps = 0x40,
BSoD = 0x29a
}
[Flags]
public enum ShutdownMod : uint
{
None = 0x00,
Force = 0x04,
ForceIfHung = 0x10
}
public static unsafe void RaiseEvent(ShutdownMode mode, ShutdownReason reason = ShutdownReason.MinorOther, ShutdownMod mod = ShutdownMod.None)
public static void RaiseEvent(ShutdownMode mode, ShutdownReason reason = ShutdownReason.MinorOther,
ShutdownMod mod = ShutdownMod.None)
{
if (mode == ShutdownMode.BSoD)
{
bool t1;
uint t2;
RtlAdjustPrivilege(19, true, false, out t1);
NtRaiseHardError(0xc0000022, 0, 0, IntPtr.Zero, 6, out t2);
ntdll.RtlAdjustPrivilege(19, true, false, out bool _);
ntdll.NtRaiseHardError(0xc0000022, 0, 0, IntPtr.Zero, 6, out uint _);
}
else
{
Privileges.EnablePrivilege(SecurityEntity.SE_SHUTDOWN_NAME);
ExitWindowsEx((ExitWindows)((uint)mode | (uint)mod), reason);
EnablePrivilege(SecurityEntity.SeShutdownPrivilege);
user32.ExitWindowsEx((ExitWindows) ((uint) mode | (uint) mod), reason);
}
}
}
class ugly_copy_paste_code
{
/*
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name,
ref long pluid);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool ExitWindowsEx(int flg, int rea);
[Flags()]
public enum ExitWindowsValues
{
Logoff = 0x00000000,
Shutdown = 0x00000001,
Reboot = 0x00000002,
Force = 0x00000004,
Poweroff = 0x00000008,
For
}
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
internal const int EWX_LOGOFF = 0x00000000;
internal const int EWX_SHUTDOWN = 0x00000001;
internal const int EWX_REBOOT = 0x00000002;
internal const int EWX_FORCE = 0x00000004;
internal const int EWX_POWEROFF = 0x00000008;
internal const int EWX_FORCEIFHUNG = 0x00000010;
private void DoExitWin(int flg)
{
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
ExitWindowsEx(flg, 0);
}
*/
}
}
}

View File

@ -1,281 +1,173 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using CC_Functions.W32.Native;
namespace CC_Functions.W32
{
public class Privileges
public static class Privileges
{
public enum SecurityEntity
{
SeAssignPrimaryTokenPrivilege,
SeAuditPrivilege,
SeBackupPrivilege,
SeChangeNotifyPrivilege,
SeCreateGlobalPrivilege,
SeCreatePagefilePrivilege,
SeCreatePermanentPrivilege,
SeCreateSymbolicLinkPrivilege,
SeCreateTokenPrivilege,
SeDebugPrivilege,
SeDelegateSessionUserImpersonatePrivilege,
SeEnableDelegationPrivilege,
SeImpersonatePrivilege,
SeIncreaseBasePriorityPrivilege,
SeIncreaseWorkingSetPrivilege,
SeIncreaseQuotaPrivilege,
SeLoadDriverPrivilege,
SeLockMemoryPrivilege,
SeMachineAccountPrivilege,
SeManageVolumePrivilege,
SeProfileSingleProcessPrivilege,
SeRelabelPrivilege,
SeRemoteShutdownPrivilege,
SeRestorePrivilege,
SeSecurityPrivilege,
SeShutdownPrivilege,
SeSyncAgentPrivilege,
SeSystemEnvironmentPrivilege,
SeSystemProfilePrivilege,
SeSystemtimePrivilege,
SeTakeOwnershipPrivilege,
SeTcbPrivilege,
SeTimeZonePrivilege,
SeTrustedCredManAccessPrivilege,
SeUndockPrivilege,
SeUnsolicitedInputPrivilege
}
public enum SecurityEntity2
{
SE_ASSIGNPRIMARYTOKEN_NAME_TEXT,
SE_AUDIT_NAME_TEXT,
SE_BACKUP_NAME_TEXT,
SE_CHANGE_NOTIFY_NAME_TEXT,
SE_CREATE_GLOBAL_NAME_TEXT,
SE_CREATE_PAGEFILE_NAME_TEXT,
SE_CREATE_PERMANENT_NAME_TEXT,
SE_CREATE_SYMBOLIC_LINK_NAME_TEXT,
SE_CREATE_TOKEN_NAME_TEXT,
SE_DEBUG_NAME_TEXT,
SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME_TEXT,
SE_ENABLE_DELEGATION_NAME_TEXT,
SE_IMPERSONATE_NAME_TEXT,
SE_INC_BASE_PRIORITY_NAME_TEXT,
SE_INC_WORKING_SET_NAME_TEXT,
SE_INCREASE_QUOTA_NAME_TEXT,
SE_LOAD_DRIVER_NAME_TEXT,
SE_LOCK_MEMORY_NAME_TEXT,
SE_MACHINE_ACCOUNT_NAME_TEXT,
SE_MANAGE_VOLUME_NAME_TEXT,
SE_PROF_SINGLE_PROCESS_NAME_TEXT,
SE_RELABEL_NAME_TEXT,
SE_REMOTE_SHUTDOWN_NAME_TEXT,
SE_RESTORE_NAME_TEXT,
SE_SECURITY_NAME_TEXT,
SE_SHUTDOWN_NAME_TEXT,
SE_SYNC_AGENT_NAME_TEXT,
SE_SYSTEM_ENVIRONMENT_NAME_TEXT,
SE_SYSTEM_PROFILE_NAME_TEXT,
SE_SYSTEMTIME_NAME_TEXT,
SE_TAKE_OWNERSHIP_NAME_TEXT,
SE_TCB_NAME_TEXT,
SE_TIME_ZONE_NAME_TEXT,
SE_TRUSTED_CREDMAN_ACCESS_NAME_TEXT,
SE_UNDOCK_NAME_TEXT,
SE_UNSOLICITED_INPUT_NAME_TEXT
}
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int ERROR_NOT_ALL_ASSIGNED = 1300;
internal const uint TOKEN_QUERY = 0x0008;
internal const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
public static void EnablePrivilege(SecurityEntity securityEntity)
{
if (!Enum.IsDefined(typeof(SecurityEntity), securityEntity))
throw new InvalidEnumArgumentException("securityEntity", (int)securityEntity, typeof(SecurityEntity));
var securityEntityValue = GetSecurityEntityValue(securityEntity);
throw new InvalidEnumArgumentException("securityEntity", (int) securityEntity, typeof(SecurityEntity));
string securityEntityValue = securityEntity.ToString();
try
{
var locallyUniqueIdentifier = new NativeMethods.LUID();
if (NativeMethods.LookupPrivilegeValue(null, securityEntityValue, ref locallyUniqueIdentifier))
LUID locallyUniqueIdentifier = new LUID();
if (advapi32.LookupPrivilegeValue(null, securityEntityValue, ref locallyUniqueIdentifier))
{
var TOKEN_PRIVILEGES = new NativeMethods.TOKEN_PRIVILEGES();
TOKEN_PRIVILEGES.PrivilegeCount = 1;
TOKEN_PRIVILEGES.Attributes = NativeMethods.SE_PRIVILEGE_ENABLED;
TOKEN_PRIVILEGES.Luid = locallyUniqueIdentifier;
var tokenHandle = IntPtr.Zero;
TOKEN_PRIVILEGES TOKEN_PRIVILEGES = new TOKEN_PRIVILEGES
{
PrivilegeCount = 1,
Attributes = SE_PRIVILEGE_ENABLED,
Luid = locallyUniqueIdentifier
};
IntPtr tokenHandle = IntPtr.Zero;
try
{
var currentProcess = NativeMethods.GetCurrentProcess();
if (NativeMethods.OpenProcessToken(currentProcess, NativeMethods.TOKEN_ADJUST_PRIVILEGES | NativeMethods.TOKEN_QUERY, out tokenHandle))
IntPtr currentProcess = kernel32.GetCurrentProcess();
if (advapi32.OpenProcessToken(currentProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out tokenHandle))
{
if (NativeMethods.AdjustTokenPrivileges(tokenHandle, false,
ref TOKEN_PRIVILEGES,
1024, IntPtr.Zero, IntPtr.Zero))
if (advapi32.AdjustTokenPrivileges(tokenHandle, false, ref TOKEN_PRIVILEGES, 1024,
IntPtr.Zero, IntPtr.Zero))
{
var lastError = Marshal.GetLastWin32Error();
if (lastError == NativeMethods.ERROR_NOT_ALL_ASSIGNED)
{
var win32Exception = new Win32Exception();
throw new InvalidOperationException("AdjustTokenPrivileges failed.", win32Exception);
}
if (Marshal.GetLastWin32Error() == ERROR_NOT_ALL_ASSIGNED)
throw new InvalidOperationException("AdjustTokenPrivileges failed.",
new Win32Exception());
}
else
{
var win32Exception = new Win32Exception();
throw new InvalidOperationException("AdjustTokenPrivileges failed.", win32Exception);
}
throw new InvalidOperationException("AdjustTokenPrivileges failed.",
new Win32Exception());
}
else
{
var win32Exception = new Win32Exception();
var exceptionMessage = string.Format(CultureInfo.InvariantCulture,
"OpenProcessToken failed. CurrentProcess: {0}",
currentProcess.ToInt32());
throw new InvalidOperationException(exceptionMessage, win32Exception);
}
throw new InvalidOperationException(
string.Format(CultureInfo.InvariantCulture,
"OpenProcessToken failed. CurrentProcess: {0}", currentProcess.ToInt32()),
new Win32Exception());
}
finally
{
if (tokenHandle != IntPtr.Zero)
NativeMethods.CloseHandle(tokenHandle);
kernel32.CloseHandle(tokenHandle);
}
}
else
{
var win32Exception = new Win32Exception();
var exceptionMessage = string.Format(CultureInfo.InvariantCulture,
"LookupPrivilegeValue failed. SecurityEntityValue: {0}",
securityEntityValue);
throw new InvalidOperationException(exceptionMessage, win32Exception);
}
throw new InvalidOperationException(
string.Format(CultureInfo.InvariantCulture,
"LookupPrivilegeValue failed. SecurityEntityValue: {0}", securityEntityValue),
new Win32Exception());
}
catch (Exception e)
{
var exceptionMessage = string.Format(CultureInfo.InvariantCulture,
"GrandPrivilege failed. SecurityEntity: {0}",
securityEntityValue);
throw new InvalidOperationException(exceptionMessage, e);
throw new InvalidOperationException(
string.Format(CultureInfo.InvariantCulture, "GrantPrivilege failed. SecurityEntity: {0}",
securityEntityValue), e);
}
}
/// <summary>
/// Gets the security entity value.
/// </summary>
/// <param name="securityEntity">The security entity.</param>
private static string GetSecurityEntityValue(SecurityEntity securityEntity)
{
switch (securityEntity)
{
case SecurityEntity.SE_ASSIGNPRIMARYTOKEN_NAME:
return "SeAssignPrimaryTokenPrivilege";
case SecurityEntity.SE_AUDIT_NAME:
return "SeAuditPrivilege";
case SecurityEntity.SE_BACKUP_NAME:
return "SeBackupPrivilege";
case SecurityEntity.SE_CHANGE_NOTIFY_NAME:
return "SeChangeNotifyPrivilege";
case SecurityEntity.SE_CREATE_GLOBAL_NAME:
return "SeCreateGlobalPrivilege";
case SecurityEntity.SE_CREATE_PAGEFILE_NAME:
return "SeCreatePagefilePrivilege";
case SecurityEntity.SE_CREATE_PERMANENT_NAME:
return "SeCreatePermanentPrivilege";
case SecurityEntity.SE_CREATE_SYMBOLIC_LINK_NAME:
return "SeCreateSymbolicLinkPrivilege";
case SecurityEntity.SE_CREATE_TOKEN_NAME:
return "SeCreateTokenPrivilege";
case SecurityEntity.SE_DEBUG_NAME:
return "SeDebugPrivilege";
case SecurityEntity.SE_ENABLE_DELEGATION_NAME:
return "SeEnableDelegationPrivilege";
case SecurityEntity.SE_IMPERSONATE_NAME:
return "SeImpersonatePrivilege";
case SecurityEntity.SE_INC_BASE_PRIORITY_NAME:
return "SeIncreaseBasePriorityPrivilege";
case SecurityEntity.SE_INCREASE_QUOTA_NAME:
return "SeIncreaseQuotaPrivilege";
case SecurityEntity.SE_INC_WORKING_SET_NAME:
return "SeIncreaseWorkingSetPrivilege";
case SecurityEntity.SE_LOAD_DRIVER_NAME:
return "SeLoadDriverPrivilege";
case SecurityEntity.SE_LOCK_MEMORY_NAME:
return "SeLockMemoryPrivilege";
case SecurityEntity.SE_MACHINE_ACCOUNT_NAME:
return "SeMachineAccountPrivilege";
case SecurityEntity.SE_MANAGE_VOLUME_NAME:
return "SeManageVolumePrivilege";
case SecurityEntity.SE_PROF_SINGLE_PROCESS_NAME:
return "SeProfileSingleProcessPrivilege";
case SecurityEntity.SE_RELABEL_NAME:
return "SeRelabelPrivilege";
case SecurityEntity.SE_REMOTE_SHUTDOWN_NAME:
return "SeRemoteShutdownPrivilege";
case SecurityEntity.SE_RESTORE_NAME:
return "SeRestorePrivilege";
case SecurityEntity.SE_SECURITY_NAME:
return "SeSecurityPrivilege";
case SecurityEntity.SE_SHUTDOWN_NAME:
return "SeShutdownPrivilege";
case SecurityEntity.SE_SYNC_AGENT_NAME:
return "SeSyncAgentPrivilege";
case SecurityEntity.SE_SYSTEM_ENVIRONMENT_NAME:
return "SeSystemEnvironmentPrivilege";
case SecurityEntity.SE_SYSTEM_PROFILE_NAME:
return "SeSystemProfilePrivilege";
case SecurityEntity.SE_SYSTEMTIME_NAME:
return "SeSystemtimePrivilege";
case SecurityEntity.SE_TAKE_OWNERSHIP_NAME:
return "SeTakeOwnershipPrivilege";
case SecurityEntity.SE_TCB_NAME:
return "SeTcbPrivilege";
case SecurityEntity.SE_TIME_ZONE_NAME:
return "SeTimeZonePrivilege";
case SecurityEntity.SE_TRUSTED_CREDMAN_ACCESS_NAME:
return "SeTrustedCredManAccessPrivilege";
case SecurityEntity.SE_UNDOCK_NAME:
return "SeUndockPrivilege";
default:
throw new ArgumentOutOfRangeException(typeof(SecurityEntity).Name);
}
}
}
public enum SecurityEntity
{
SE_CREATE_TOKEN_NAME,
SE_ASSIGNPRIMARYTOKEN_NAME,
SE_LOCK_MEMORY_NAME,
SE_INCREASE_QUOTA_NAME,
SE_UNSOLICITED_INPUT_NAME,
SE_MACHINE_ACCOUNT_NAME,
SE_TCB_NAME,
SE_SECURITY_NAME,
SE_TAKE_OWNERSHIP_NAME,
SE_LOAD_DRIVER_NAME,
SE_SYSTEM_PROFILE_NAME,
SE_SYSTEMTIME_NAME,
SE_PROF_SINGLE_PROCESS_NAME,
SE_INC_BASE_PRIORITY_NAME,
SE_CREATE_PAGEFILE_NAME,
SE_CREATE_PERMANENT_NAME,
SE_BACKUP_NAME,
SE_RESTORE_NAME,
SE_SHUTDOWN_NAME,
SE_DEBUG_NAME,
SE_AUDIT_NAME,
SE_SYSTEM_ENVIRONMENT_NAME,
SE_CHANGE_NOTIFY_NAME,
SE_REMOTE_SHUTDOWN_NAME,
SE_UNDOCK_NAME,
SE_SYNC_AGENT_NAME,
SE_ENABLE_DELEGATION_NAME,
SE_MANAGE_VOLUME_NAME,
SE_IMPERSONATE_NAME,
SE_CREATE_GLOBAL_NAME,
SE_CREATE_SYMBOLIC_LINK_NAME,
SE_INC_WORKING_SET_NAME,
SE_RELABEL_NAME,
SE_TIME_ZONE_NAME,
SE_TRUSTED_CREDMAN_ACCESS_NAME
}
internal static class NativeMethods
{
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LookupPrivilegeValue(string lpsystemname, string lpname, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AdjustTokenPrivileges(IntPtr tokenhandle,
[MarshalAs(UnmanagedType.Bool)] bool disableAllPrivileges,
[MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES newstate,
uint bufferlength, IntPtr previousState, IntPtr returnlength);
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int ERROR_NOT_ALL_ASSIGNED = 1300;
internal const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
internal const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
internal const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
internal const UInt32 TOKEN_DUPLICATE = 0x0002;
internal const UInt32 TOKEN_IMPERSONATE = 0x0004;
internal const UInt32 TOKEN_QUERY = 0x0008;
internal const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
internal const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
internal const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
internal const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
internal const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
internal const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
internal const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr GetCurrentProcess();
[DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool OpenProcessToken(IntPtr processHandle,
uint desiredAccesss,
out IntPtr tokenHandle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern Boolean CloseHandle(IntPtr hObject);
public static SecurityEntity EntityToEntity(SecurityEntity2 entity) => (SecurityEntity) entity;
[StructLayout(LayoutKind.Sequential)]
internal struct LUID
{
internal Int32 LowPart;
internal UInt32 HighPart;
internal int LowPart;
internal uint HighPart;
}
[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGES
{
internal Int32 PrivilegeCount;
internal int PrivilegeCount;
internal LUID Luid;
internal Int32 Attributes;
internal int Attributes;
}
}
}
}

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CC-Functions.W32")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CC-Functions.W32")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("23de4ae0-5075-4ccc-8440-4d131ca0fbba")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

46
W32/ScreenMan.cs Normal file
View File

@ -0,0 +1,46 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using CC_Functions.W32.DCDrawer;
using CC_Functions.W32.Native;
namespace CC_Functions.W32
{
public static class ScreenMan
{
private const int SRCCOPY = 13369376;
public static Image CaptureScreen() => CaptureWindow(user32.GetDesktopWindow());
public static Image CaptureWindow(IntPtr handle)
{
IntPtr hdcSrc = user32.GetWindowDC(handle);
RECT windowRect = new RECT();
user32.GetWindowRect(handle, ref windowRect);
IntPtr hdcDest = gdi32.CreateCompatibleDC(hdcSrc);
IntPtr hBitmap = gdi32.CreateCompatibleBitmap(hdcSrc, windowRect.Width, windowRect.Height);
IntPtr hOld = gdi32.SelectObject(hdcDest, hBitmap);
gdi32.BitBlt(hdcDest, 0, 0, windowRect.Width, windowRect.Height, hdcSrc, 0, 0, SRCCOPY);
gdi32.SelectObject(hdcDest, hOld);
gdi32.DeleteDC(hdcDest);
user32.ReleaseDC(handle, hdcSrc);
Image img = Image.FromHbitmap(hBitmap);
gdi32.DeleteObject(hBitmap);
return img;
}
public static void Draw(Image img)
{
using (IDCDrawer drawerBuffered = GetDrawer()) drawerBuffered.Graphics.DrawImage(img, GetBounds());
}
public static IDCDrawer GetDrawer(bool buffer = true)
{
IntPtr ptr = user32.GetDC(IntPtr.Zero);
return buffer ? (IDCDrawer) new DCBuffered(ptr) : new DCUnbuffered(ptr);
}
public static Rectangle GetBounds() => Screen.PrimaryScreen.Bounds;
public static void Refresh() => shell32.SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
}
}

10
W32/Security.cs Normal file
View File

@ -0,0 +1,10 @@
using System.Security.Principal;
namespace CC_Functions.W32
{
public static class MiscFunctions
{
public static bool IsAdministrator =>
new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
}
}

23
W32/Time.cs Normal file
View File

@ -0,0 +1,23 @@
using System;
using CC_Functions.W32.Native;
namespace CC_Functions.W32
{
public static class Time
{
public static void Set(DateTime time)
{
time = time.ToUniversalTime();
kernel32.SYSTEMTIME st = new kernel32.SYSTEMTIME
{
wYear = (short) time.Year,
wMonth = (short) time.Month,
wDay = (short) time.Day,
wHour = (short) time.Hour,
wMinute = (short) time.Minute,
wSecond = (short) time.Second
};
kernel32.SetSystemTime(ref st);
}
}
}

View File

@ -1,55 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{23DE4AE0-5075-4CCC-8440-4D131CA0FBBA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CC_Functions.W32</RootNamespace>
<AssemblyName>CC-Functions.W32</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<LangVersion>8</LangVersion>
<UseWindowsForms>true</UseWindowsForms>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Deterministic>false</Deterministic>
<Authors>JFronny</Authors>
<Description>W32 Additions for CC-Functions</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
</PropertyGroup>
<ItemGroup>
<Compile Update="Forms\DataGridViewNumericUpDownEditingControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Update="Forms\RotatingIndicator.cs">
<SubType>Component</SubType>
</Compile>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\W32.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\W32.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Hooks.cs" />
<Compile Include="Power.cs" />
<Compile Include="Privileges.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Wnd32.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,136 +1,389 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CC_Functions.W32.Native;
namespace CC_Functions.W32
{
public class Wnd32 : IEquatable<Wnd32>
/// <summary>
/// Object representing a window handle in the Windows API. Provides a simplified interface for basic interactions
/// </summary>
public sealed class Wnd32 : IEquatable<Wnd32>
{
#region Exposed
#region CreateInstance
Wnd32(IntPtr wndref) => hWnd = wndref;
public static Wnd32 fromHandle(IntPtr handle) => new Wnd32(handle);
public static Wnd32 fromMetadata(string lpClassName = null, string lpWindowName = null) => fromHandle(FindWindow(lpClassName, lpWindowName));
public static Wnd32 fromPoint(Point point) => fromHandle(WindowFromPoint(point.X, point.Y));
public static Wnd32 fromForm(Form form) => fromHandle(form.Handle);
public static Wnd32 foreground() => fromHandle(GetForegroundWindow());
#endregion
#region InstanceActions
public string title { get {
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
} set {
SetWindowText(hWnd, value);
} }
public Rectangle position { get {
RECT Rect = new RECT();
GetWindowRect(hWnd, ref Rect);
return new Rectangle(new Point(Rect.left, Rect.top), new Size(Rect.right - Rect.left, Rect.bottom - Rect.top));
} set {
RECT Rect = new RECT();
GetWindowRect(hWnd, ref Rect);
MoveWindow(hWnd, value.X, value.Y, value.Width, value.Height, true);
} }
public bool isForeground { get {
return GetForegroundWindow() == hWnd;
} set {
if (value)
SetForegroundWindow(hWnd);
else
throw new InvalidOperationException("You can't set a Window not to be in the foreground. Move another one over it!");
}
}
public bool enabled { get {
return IsWindowEnabled(hWnd);
} set {
EnableWindow(hWnd, value);
}
}
public void MakeOverlay() => _ = SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
public bool Destroy()
#region Exposed
#region CreateInstance
private Wnd32(IntPtr handle) => HWnd = handle;
/// <summary>
/// Base method. Generates a window object from the specified handle
/// </summary>
/// <param name="handle">The handle</param>
/// <returns>The window</returns>
public static Wnd32 FromHandle(IntPtr handle) => new Wnd32(handle);
/// <summary>
/// Gets the main window of the process
/// </summary>
/// <param name="process">The process</param>
/// <returns>The window. Might be IntPtr.Zero</returns>
public static Wnd32 GetProcessMain(Process process) => FromHandle(process.MainWindowHandle);
/// <summary>
/// Generates a window from metadata. Parameters should be null if they are not used
/// </summary>
/// <param name="lpClassName">
/// The class name of the window. Use the name you found before using the ClassName-parameter of
/// a window
/// </param>
/// <param name="lpWindowName">The windows name (title)</param>
/// <returns>The window. Might be IntPtr.Zero</returns>
public static Wnd32 FromMetadata(string? lpClassName = null, string? lpWindowName = null) =>
FromHandle(user32.FindWindow(lpClassName, lpWindowName));
/// <summary>
/// Gets the window that is visible at the specified point
/// </summary>
/// <param name="point">The point to scan</param>
/// <returns>The window. Might be IntPtr.Zero</returns>
public static Wnd32 FromPoint(Point point) => FromHandle(user32.WindowFromPoint(point.X, point.Y));
/// <summary>
/// Gets all windows at the specific point
/// </summary>
/// <param name="point">The point to scan</param>
/// <param name="visible">Whether windows need to be visible</param>
/// <returns>The windows</returns>
public static Wnd32[] AllFromPoint(Point point, bool visible = false) =>
All.Where(s => s.Position.Contains(point) && s.Shown || !visible).ToArray();
/// <summary>
/// Gets the window associated with the forms handle
/// </summary>
/// <param name="form">Form to get window from</param>
/// <returns>The window. Might be IntPtr.Zero</returns>
public static Wnd32 FromForm(Form form) => FromHandle(form.Handle);
/// <summary>
/// Gets ALL windows. In most cases you will want to use Wnd32.Visible
/// </summary>
/// <exception cref="Win32Exception"></exception>
public static Wnd32[] All
{
if (DestroyWindow(hWnd))
return true;
else
get
{
_windowHandles = new List<IntPtr>();
if (!user32.EnumDesktopWindows(IntPtr.Zero, FilterCallback, IntPtr.Zero))
throw new Win32Exception("There was a native error. This should never happen!");
return _windowHandles.Select(FromHandle).ToArray();
}
}
/// <summary>
/// Gets all visible windows
/// </summary>
public static Wnd32[] Visible =>
All.Where(s => s.Shown).ToArray();
/// <summary>
/// Gets the foreground window
/// </summary>
public static Wnd32 Foreground => FromHandle(user32.GetForegroundWindow());
/// <summary>
/// The current programs console window. Do NOT use this if you are not targeting a console app or allocating a console
/// </summary>
public static Wnd32 ConsoleWindow => FromHandle(kernel32.GetConsoleWindow());
#endregion CreateInstance
#region InstanceActions
public Wnd32[] Children
{
get
{
List<IntPtr> childHandles = new List<IntPtr>();
GCHandle gcChildHandlesList = GCHandle.Alloc(childHandles);
IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildHandlesList);
try
{
user32.EnumChildWindows(HWnd, EnumWindow, pointerChildHandlesList);
}
finally
{
gcChildHandlesList.Free();
}
return childHandles.Select(FromHandle).ToArray();
}
}
public Wnd32 Parent
{
get
{
IntPtr result = user32.GetParent(HWnd);
if (result == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
return FromHandle(result);
}
}
/// <summary>
/// The windows title
/// </summary>
public string Title
{
get
{
int length = user32.GetWindowTextLength(HWnd);
StringBuilder sb = new StringBuilder(length + 1);
user32.GetWindowText(HWnd, sb, sb.Capacity);
return sb.ToString();
}
set => user32.SetWindowTextW(HWnd, value);
}
/// <summary>
/// The windows position in screen-space
/// </summary>
public Rectangle Position
{
get
{
RECT rect = new RECT();
user32.GetWindowRect(HWnd, ref rect);
return new Rectangle(new Point(rect.Left, rect.Top),
new Size(rect.Width, rect.Height));
}
set
{
RECT rect = new RECT();
user32.GetWindowRect(HWnd, ref rect);
user32.MoveWindow(HWnd, value.X, value.Y, value.Width, value.Height, true);
}
}
/// <summary>
/// Gets whether the window is the foreground window or brings it to the front. "False" must not be assigned!
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when the value is "False"</exception>
public bool IsForeground
{
get => user32.GetForegroundWindow() == HWnd;
set
{
if (value)
user32.SetForegroundWindow(HWnd);
else
throw new InvalidOperationException(
"You can't set a Window not to be in the foreground. Move another one over it!");
}
}
/// <summary>
/// Whether the window is enabled. Functionally similar to WinForms' "Control.Enabled"
/// </summary>
public bool Enabled
{
get => user32.IsWindowEnabled(HWnd);
set => user32.EnableWindow(HWnd, value);
}
/// <summary>
/// Gets the windows icon
/// </summary>
public Icon Icon
{
get
{
IntPtr hIcon = user32.SendMessage(HWnd, 0x7F, 1, 0);
if (hIcon == IntPtr.Zero)
hIcon = user32.SendMessage(HWnd, 0x7F, 0, 0);
if (hIcon == IntPtr.Zero)
hIcon = user32.SendMessage(HWnd, 0x7F, 2, 0);
return Icon.FromHandle(hIcon);
}
}
/// <summary>
/// Whether the window is visible
/// </summary>
public bool Shown
{
get => user32.IsWindowVisible(HWnd);
set => user32.ShowWindow(HWnd, value ? 9 : 0);
}
/// <summary>
/// Gets the windows class name, This is basically only useful for finding window class-names of specified programs
/// </summary>
public string ClassName
{
get
{
StringBuilder className = new StringBuilder(256);
user32.GetClassName(HWnd, className, className.Capacity);
return className.ToString();
}
}
/// <summary>
/// Sets the window state
/// </summary>
public FormWindowState State
{
get
{
int style = user32.GetWindowLong(HWnd, -16);
if ((style & 0x01000000) == 0x01000000)
return FormWindowState.Maximized;
if ((style & 0x20000000) == 0x20000000)
return FormWindowState.Minimized;
return FormWindowState.Normal;
}
set
{
switch (value)
{
case FormWindowState.Minimized:
user32.ShowWindow(HWnd, 11);
break;
case FormWindowState.Normal:
user32.ShowWindow(HWnd, 1);
break;
case FormWindowState.Maximized:
user32.ShowWindow(HWnd, 3);
break;
default:
throw new ArgumentException("The provided WindowState was invalid", "value");
}
}
}
/// <summary>
/// Overlays the window over others
/// </summary>
public bool Overlay
{
set
{
Rectangle tmp = Position;
user32.SetWindowPos(HWnd, value ? new IntPtr(-1) : new IntPtr(-2), tmp.X, tmp.Y, tmp.Width, tmp.Height,
value ? (uint) 3 : 0);
}
}
/// <summary>
/// Forces the window to close
/// </summary>
/// <exception cref="Exception">Thrown if the window could not be closed</exception>
public void Destroy()
{
if (!user32.DestroyWindow(HWnd))
throw new Exception("Failed.");
}
public bool stillExists => IsWindow(hWnd);
public override string ToString() => hWnd.ToString() + "; " + title + "; " + position.ToString();
/// <summary>
/// Whether the IntPtr is a window and still exists
/// </summary>
public bool StillExists => user32.IsWindow(HWnd);
/// <summary>
/// Creates a user-readable string from the windows hWnd, title and position
/// </summary>
/// <returns>The created string</returns>
public override string ToString() => $"{HWnd}; {Title}; {Position}";
/// <summary>
/// Equality operator, uses the hWnd field
/// </summary>
/// <param name="obj">Object (Window) to compare</param>
/// <returns>Equality result</returns>
public override bool Equals(object obj) => Equals(obj as Wnd32);
public bool Equals(Wnd32 other) => other != null && EqualityComparer<IntPtr>.Default.Equals(hWnd, other.hWnd);
public override int GetHashCode() => -75345830 + EqualityComparer<IntPtr>.Default.GetHashCode(hWnd);
public static bool operator ==(Wnd32 left, Wnd32 right) => EqualityComparer<Wnd32>.Default.Equals(left, right);
public static bool operator !=(Wnd32 left, Wnd32 right) => !(left == right);
#endregion
#endregion
#region W32
public IntPtr hWnd;
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// Equality operator, uses the hWnd field
/// </summary>
/// <param name="other">Window to compare</param>
/// <returns>Equality result</returns>
public bool Equals(Wnd32 other) => !IsNull(other) && other != null && HWnd.Equals(other.HWnd);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(int xPoint, int yPoint);
/// <summary>
/// Equality operator, uses the hWnd field
/// </summary>
/// <returns>Equality result</returns>
public override int GetHashCode() => HWnd.GetHashCode();
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool SetWindowText(IntPtr hWnd, string lpString);
/// <summary>
/// Equality operator, uses the hWnd field
/// </summary>
/// <param name="left">Window to compare</param>
/// <param name="right">Window to compare</param>
/// <returns>Equality result</returns>
public static bool operator ==(Wnd32 left, Wnd32 right) => !AreNull(left, right) && left.HWnd == right.HWnd;
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
/// <summary>
/// Equality operator, uses the hWnd field
/// </summary>
/// <param name="left">Window to compare</param>
/// <param name="right">Window to compare</param>
/// <returns>Equality result</returns>
public static bool operator !=(Wnd32 left, Wnd32 right) => AreNull(left, right) || left.HWnd != right.HWnd;
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
private static bool AreNull(params Wnd32[] windows) => windows.Any(IsNull);
[DllImport("user32.dll")]
static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowEnabled(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DestroyWindow(IntPtr hwnd);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, ExactSpelling = true, SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);
struct RECT
private static bool IsNull(Wnd32 window)
{
public int left;
public int top;
public int right;
public int bottom;
try
{
window.ToString();
return false;
}
catch (NullReferenceException)
{
return true;
}
}
#endregion InstanceActions
#endregion Exposed
#region Internal
/// <summary>
/// The windows' handle
/// </summary>
public readonly IntPtr HWnd;
private static List<IntPtr> _windowHandles;
private static bool FilterCallback(IntPtr hWnd, int lParam)
{
StringBuilder sbTitle = new StringBuilder(1024);
user32.GetWindowText(hWnd, sbTitle, 1024);
_windowHandles.Add(hWnd);
return true;
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
{
GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindow(IntPtr hWnd);
#endregion
if (gcChildhandlesList.Target == null) return false;
List<IntPtr> childHandles = gcChildhandlesList.Target as List<IntPtr>;
childHandles?.Add(hWnd);
return true;
}
#endregion Internal
}
}
}

5
renovate.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": [
"config:base"
]
}