duangsuse::Echo
#C #Windows 我来总结一下用了哪些 API 怎么用,方便背 首先,你需要 aero.h [@ysc3839's gist] 这个 undocumented API header 其中包括必须的数据类型和子程序定义 #CSharp 版:需要使用 C# 的 P/Invoke (System.Runtime.InteropServices)特性 1. 对于外部的 C 结构体,只需要使用 struct 关键字定义,然后加上 [StructLayout(LayoutKind.Sequential)]…
== 无关的 Win32 Form API
首先这里的 Aero 就是 Windows 所谓的毛玻璃特效
既然都用过这个特效,那都知道这个特效有三个最重要的参数:
1. 毛玻璃的特效状态,比如是否启用
2. 毛玻璃的颜色(color)、毛玻璃的模糊度、边缘和渐变色什么的,这些统称为毛玻璃效果的属性(attribute)
3. 毛玻璃的大小矩形框(这个是作为一个矩形视图也要有的)
4. Aero 是可以指定窗口动画的
== 有关的 P/Invkoke 封送(System.Runtime.InteropServices.Marshal)API
注意:
1. 如果你使用 deleteOld,且 ptr output 没有被正确设置,则可能
此外,要使用 C# 的 FFI 特性,还有
—
那实际上只需要用这两个 API,一个 Getter 一个 Setter,都 Take 一个 Window Handle,一个
—
那
后面的
== 这个合成属性的使用
首先,准备好目标窗体
然后直接使用 setter
那既然如此为什么不把
以上讲到的是 CSharp P/Invoke Windows 10 Aero Hidden API 的代码,不过 Windows 7 的(默认 Aero)要使用
你学到的应该是:
1. 使用
2. 使用
3. 如何使用
4. Windows 的 Aero 混成属性:
static Application.EnableVisualStyles();—
static Application.SetCompatibleTextRenderingDefault(bool);
static Application.Run(Form);
namespace System.Windows.Forms { Form }
class Form {
protected void OnLoad(EventArgs);
}
== 有关的 Aero API首先这里的 Aero 就是 Windows 所谓的毛玻璃特效
既然都用过这个特效,那都知道这个特效有三个最重要的参数:
1. 毛玻璃的特效状态,比如是否启用
2. 毛玻璃的颜色(color)、毛玻璃的模糊度、边缘和渐变色什么的,这些统称为毛玻璃效果的属性(attribute)
3. 毛玻璃的大小矩形框(这个是作为一个矩形视图也要有的)
4. Aero 是可以指定窗口动画的
== 有关的 P/Invkoke 封送(System.Runtime.InteropServices.Marshal)API
static Int32 Marshal.SizeOf<T>();[NET 4.5.1+]
static Marshal.AllocHGlobal(Int32); 其中 H 是 Handle 的意思... 总之 Unix 系 Programmer 的直觉还是有点无法和 Win32 MSVC 系无法统一啊(UNIX 是直接 void *malloc(size_t);
static Marshal.FreeHGlobal(Int32); 用完了别忘记放回去别人还得用static void StructureToPtr<T>(T, IntPtr, Boolean); 就是 memmove,Rust 的 ptr::write,第三个参数的意思就是复制数据之前要不要先删掉那块地方旧的分配(如果是新分配到的内存就不需要)注意:
1. 如果你使用 deleteOld,且 ptr output 没有被正确设置,则可能
破坏原有有效数据
2. 如果你不使用 deleteOld,且 ptr output 本来就已经没用了,则可能导致内存泄漏 (滑稽)此外,要使用 C# 的 FFI 特性,还有
new T {} where T: structure 和 ref T 拿到指针的特性—
那实际上只需要用这两个 API,一个 Getter 一个 Setter,都 Take 一个 Window Handle,一个
struct _WINDOWCOMPOSITIONATTRIBDATA *
bool __stdcall pfnGetWindowCompositionAttribute(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
bool __stdcall pfnSetWindowCompositionAttribute(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
我实在不知道 typedef 还可以这么用 typedef int (*add2)(int);... 等于这个 type 的名字是 (*add2)(int), 看起来根本不是一个标识符... 或者说根本不存在名字(int (*)(int) 本身就是 C 的函数指针类型)... 奇妙—
那
WINDOWCOMPOSITIONATTRIBDATA这个类型又是啥子呢?它就是 Windows 的窗口混成器参数:
struct {
enum WINDOWCOMPOSITIONATTRIB Attrib;
void *pvData; size_t cbData;
}
其中 WINDOWCOMPOSITIONATTRIB 有很多单选项啦,比如 WCA_EXCLUDED_FROM_LIVEPREVIEW (不允许实时预览)、WCA_TRANSITIONS_FORCEDISABLED(不允许移动?)后面的
void *pvData 和 size_t cbData 是一家的,它们指向一个内存切片(buffer; slice)一般可以被解释为struct ACCENT_POLICY {
enum ACCENT_STATE AccentState;
DWORD AccentFlags;
DWORD GradientColor;
DWORD AnimationId;
}
enum ACCENT_STATE {
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809
ACCENT_INVALID_STATE = 6
}
一般直接用毛玻璃(BLUR BEHIND)== 这个合成属性的使用
首先,准备好目标窗体
hwnd 和 Aero 参数 struct AccentPolicy
static int SetAero(IntPtr hwnd, ref AccentPolicy policy) {...}
准备数据 var wcaps = new WindowsCompositionAttributeData { Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY };
wcaps.SizeOfData = Marshal.SizeOf<AccentPolicy>();
wcaps.Data = policy;
Trumeet 是直接复制了别人的 SizeOf, AllocHGlobal, StructureToPtr, FreeHGlobal... 走了一遍 StructToNewAlloc 的流程,但是其实拿到此结构的指针传递数据就可以了,也不一定得堆分配。然后直接使用 setter
attributeDatas[AccentPolicy] = ...(拟 return SetWindowCompositionAttribute(hwnd, ref wcaps);
Aero 参数 AccentPolicy 怎么拿?首先我们得清楚,架构此结构体的方法不能返回一个本地分配的 AccentPolicy... 其次最好也不要返回一个 struct AccentPolicy,因为它要复制比较多的数据....那既然如此为什么不把
SetAero 当成是 MakeAeroEffect 子程序的辅助者,然后直接在 MakeAeroEffect 里分配?static int MakeAeroEffect(IntPtr hwnd, AeroState st, int aeroFlags = 0, int gradientColor = 0x00000000, int animId = 0) {...}
这里就对应到了之前的四个特效属性 var params = new AccentPolicy { AccentState=st, AccentFlags=aeroFlags, GradientColor=gradientColor, AnimationId=animId };
然后按照约定,调用 setAero
return setAero(hwnd, ref params);
就 OK 了以上讲到的是 CSharp P/Invoke Windows 10 Aero Hidden API 的代码,不过 Windows 7 的(默认 Aero)要使用
DwmApi.dll 和 DwmExtendFrameIntoClientArea 来把 window 的某个 frame 化为新混成区域,因为默认有 Aero glass你学到的应该是:
1. 使用
[DllImport(...)] extern ... 动态链接外部函数库;使用 [StructLayout(LayoutKind.Sequential)] 定义可以被正确传递给 C FFI 的结构体2. 使用
IntPtr 和 ref (当然它们不如 SafeHandle,不过后者是只有真正的 C#+Windows CNI 原生接口 程序员才知道)3. 如何使用
SetWindowCompositionAttribute 设置指定窗体混成属性4. Windows 的 Aero 混成属性:
AccentPolicy 和 enum AccentState,它的四个子属性(状态、特性标志、渐变、动画效果)Docs
Marshal Class (System.Runtime.InteropServices)
Provides a collection of methods for allocating unmanaged memory, copying unmanaged memory blocks, and converting managed to unmanaged types, as well as other miscellaneous methods used when interacting with unmanaged code.
duangsuse::Echo
aero-example.c
Win32 API 真的是很不友好... 要记很多东西,而且比如那个 dialog 本来应该是属性的东西却被弄成 callback Query 的形式,真是让人有点难记
虽然所有人看着文档都能写出代码而已,我会很希望默写下来看到的每一行代码... 😭
虽然所有人看着文档都能写出代码而已,我会很希望默写下来看到的每一行代码... 😭
Forwarded from dnaugsuz
说起来我之前以为不能在 Kotlin 里面
现在想来居然可以!
null ?: return 的因为 return 是 Nothing,另一个想法就是表达式求值不应该被中断... (这明显是错误的)现在想来居然可以!
Forwarded from Yuuta
原来 GetModuleHandle(0) 的参数是 LPCSTR
Forwarded from Yuuta
我就把 0 理解为 Null 了
Forwarded from Richard Yu
C里面一般是 #define NULL (void*)0 的,C++ 里面 nullptr 转换为指针的时候也是 0。
Forwarded from dnaugsuz
... 真的不该这么写的,以后千万千万不要把
LLVM Cookbook 这本书里,把所有
书中有一个大概类似这样的子程序:
(
nullptr 、(char*) *{'\0'}; 之类的东西写成 0 了,很多人以为代码短一点很秀,其实反而会导致很大混淆,这是不正确的LLVM Cookbook 这本书里,把所有
* 指针类型的空指针值全写成了 0,我眼睛都要看瞎了书中有一个大概类似这样的子程序:
(
ConstLiteral::Codegen override 了超类 BaseAst 的 virtual Value *Codegen();)Value *ConstLiteral::Codegen() override {
switch (type) {
case vaConstInt: return ConstantInt::get(Type::getInt32Ty(vCtx), (int) value);
default: return 0;
}
}
有的时候父语法树节点依赖子节点的值,然后要 null safe,他是这么判断的(比如 for i=0, 10 循环节点):if (initval.Codegen() == 0) return 0;其实要这么写(也很辣鸡莫名其妙)我都能接受,但他偏偏写了这么多
0...if (initval.Codegen() /*!=0*/) {...}
我的天啊,简直看瞎了,当时我就觉得他们都是些只会抄代码的货,虽然后面的确是有干货,为什么编程风格这么差Forwarded from dnaugsuz
所以以后觉得
这么混淆的确是有点误人子弟,别人看第一眼还以为是
"" 难看就弄一个 EMPTY_CHARP (当然 Windows 里显然要叫 EMPTY_LPCHAR...) 常量算了这么混淆的确是有点误人子弟,别人看第一眼还以为是
GetModuleHandle 函数处理了特别的值,其实只是 "" 而已Forwarded from yunfeng
隔壁 java 留下了眼泪(
Forwarded from dnaugsuz
Jawa 也有一些可以“跨运行时平台”的实现,比如 JSweet transpiler
JVM 本身对 C, C++ 等所谓 Native 语言的编译器也有实现的,至少人家还支持 JNI 扩展底层访问性呢 [比如说这个]
曾经的 GCJ (GNU Compiler for Java) 也是支持 Java -> native code 的
现在 GraalVM 、之前 ExcelsiorJET 不也在吹 AOT 编译的说
JVM 本身对 C, C++ 等所谓 Native 语言的编译器也有实现的,至少人家还支持 JNI 扩展底层访问性呢 [比如说这个]
曾经的 GCJ (GNU Compiler for Java) 也是支持 Java -> native code 的
现在 GraalVM 、之前 ExcelsiorJET 不也在吹 AOT 编译的说
JSweet
JSweet: a transpiler to write JavaScript programs in Java
JSweet is an open transpiler from Java to TypeScript/JavaScript with more than 1000 well-typed JavaScript libraries.
Forwarded from Yuuta
不懂那么深奥的,反正 J AV A 给我的感觉就是有大又笨又老(x
Forwarded from dnaugsuz
Java 是很老,但也是 Kotlin 它干爹啊 🌝
Forwarded from Yuuta
不能完全算吧?从某种意义上说 Kotlin 是 “兼容” Java(x
Forwarded from dnaugsuz
C 自己也有不好的地方,比如 Null safety
你得自己写代码处理输入 ptr 可能为空但不应该为空的情况,而 Kotlin 是自动处理
如果你是比较优秀的程序员,肯定会用子程序对 raw FFI 进行高层封装(比如,一个
这一点 ice1000 的博文《形式验证、依赖类型与动态类型》讲得很好
你得自己写代码处理输入 ptr 可能为空但不应该为空的情况,而 Kotlin 是自动处理
如果你是比较优秀的程序员,肯定会用子程序对 raw FFI 进行高层封装(比如,一个
Optional<T> 会被你弄成 @Throws(XXXNotFound::class) 的形式),这样就避免了每次检查 null safety 的问题,Kotlin 只是做了对的事情,检查了 null 指针的可能性,把运行期的错误提升到了编译期,虽然 Kotlin 它不 Check Exceptions... 也有自己的道理,但完全不 sound (没 error 也没 warn)的编译检查还是....这一点 ice1000 的博文《形式验证、依赖类型与动态类型》讲得很好
Forwarded from dnaugsuz
是啊,几乎是能完全兼容 Java,至少排除元编程的情况下是完全双向兼容
但是 Java 依然还是可以用的,这点不可否认,不过我要说的是,即使是被所有人批判的 Java,也不是被人完全理解的,Java 自己看起来很简单,就算排除掉 JVM,某些细节很多资深工程师也都是说不上来,比方说所有类型表达式的求值顺序、所有语法结构、Annotation Processor 加入后的编译流程
毕竟『精通』和『创造』还是有区别的,一个是使用,一个是实现,实现意味着你得什么都知道,使用是你用什么学什么。
当然如果工程师实现过符合标准的 Java 编译器算我没说
但是 Java 依然还是可以用的,这点不可否认,不过我要说的是,即使是被所有人批判的 Java,也不是被人完全理解的,Java 自己看起来很简单,就算排除掉 JVM,某些细节很多资深工程师也都是说不上来,比方说所有类型表达式的求值顺序、所有语法结构、Annotation Processor 加入后的编译流程
毕竟『精通』和『创造』还是有区别的,一个是使用,一个是实现,实现意味着你得什么都知道,使用是你用什么学什么。
当然如果工程师实现过符合标准的 Java 编译器算我没说