2501wtl,皮肤技术
下载地址
设计目标
最重要的是使用方便
,已有程序
创建一个COM
对象,调一个方法
就可把界面
外观全部
改成Mac
风格的.
另外一个目标
是要有扩展性
.
所以,基本设计
是定义一个统一的接口
,然后用不同实现
.每一个实现
单独放在一个COMDLL
中,调用者选择一个类标
创建对象就行了.
接口的定义
:
interface ISkinX : IUnknown{[helpstring("Install Skin hook")] HRESULT InstallSkin([in] long lThreadID);[helpstring("Uninstall Skin hook")] HRESULT UninstallSkin();};
调用InstallSkin
安装皮肤
,UninstallSkin
卸掉皮肤
,lThreadID
是线程ID
.
原理
就是通过消息勾挂
改变已有控件
的外观
.
好处是可不必修改程序
已完成的标准界面
,只要勾挂上勾挂函数
,所有的界面
就都变了
,使用起来非常方便
.
原理
就是下面的调用:
SetWindowsHookEx(WH_CALLWNDPROC, HookProc, 0, lThreadID);
WH_CALLWNDPROC
勾挂,可拦截
所有线程ID
为lThreadID
的线程内的窗口消息
,这样就可处理这些消息
.
但是,光拦截消息
还不够,还必须知道是谁发出的这些消息
.
幸好,从消息的参数
里,可得到窗口句柄
,而通过窗口句柄
,可得到窗口类
.这里说的窗口类
是窗口
系统中的窗口类名
.
如,按钮的窗口类
是"按钮"
,组合框的窗口类
是"ComboBox"...
这些在MSDN
里面都可找到的,另外,还有一些文档中没有的窗口类名
,比如对话框
,有一个叫"#32770"
的类名,而菜单
,实际
上也是一个窗口
,其类名
是"#32768"
.
有了这些信息
,就可区分不同窗口处理
了.
处理消息,显然最重要的是WM_PAINT
消息.这样可重载
系统默认的绘画方式
,把控件窗口
画成想要的样子
.
但是只处理WM_PAINT
消息也是不够的
,因为控件的风格
不是一成不变
的,看看窗口xp
的显示效果,以按钮
为例,有很多种风格
,普通风格
,鼠标在按钮上的风格,鼠标按住按钮的风格,鼠标按住按钮又移动到按钮外的风格
为了实现动态
的炫目
的皮肤
效果,还需要截取一些其他消息
,如鼠标消息
.下载代码
里有Mac
按钮的一个实现,看一下
就知道了.
有了勾挂
,就可截取所有消息
,有了窗口类
,就可识别窗口类型
,对不同类型的窗口
给予不同处理
.
这样,要在勾挂函数
里面识别不同窗口和不同消息
,有大量的分发工作
,更重要的是
,光区分窗口类
还不够,同类型
的不同窗口
经常需要不同处理
,如两个按钮
窗口,大小不同,文字不同,是否有鼠标按下不同
.
这些状态
有些是可从按钮
窗口读到的,如大小和文字
,而有些
则读不到,比如是否按下鼠标
,对这些读不到的状态
,必须自己记录
,如在收到WM_LBUTTONDOWN
消息时记下
按下了按钮
.
也即,对每个窗口
,还需要记录
一些与其相应的数据
,这样在收到WM_PAINT
消息时做不同处理
.把所有这些逻辑
写在勾挂函数
里显然太麻烦了
,即使写出来也没法维护
,需要一个好的设计
.
根据面向对象
的思想,需要为每种窗口类型
写一个类,并为每个窗口
生成一个对应类的实例
,由这些实例
来处理窗口消息
,并记录必要的窗口状态数据
.
这样,就由这些对象
处理窗口消息
,怎么给这些对象
传递消息呢,可以转发勾挂函数
,不过这里用了另一个
:SubclassWindow
,SubclassWindow
的原理,就不多讲了,可参看MSDN
,其实就是替换一个窗口过程函数
.
ATL
提供了现成的支持,用起来还是很方便的,替代的窗口过程函数
不用全部自己写
,而可用消息映射宏
生成.
现在用SubclassWindow
的方式,可直接把对象
链接到窗口的消息链
中,这好像有点和勾挂函数
的功能重复了,因为勾挂函数
本来就是用来拦截消息
的.
现在SubclassWindow
以后,已可拦截
了窗口消息
,那还要勾挂函数
干什么呢?
答案是:用勾挂函数
来执行SubclassWindow
操作.原因
有两个,第一,要做的是一个皮肤插件
,想用户调用一个函数
就可改变整个界面风格
,而不是为每个窗口
调用SubclassWindow
函数;
第二,创建有些窗口
,根本不是在代码
里控制
的,如菜单窗口
,除了使用勾挂函数
,甚至不能取得菜单窗口的句柄
.
所以,必须使用勾挂函数
,但在勾挂函数
中,只处理
一个消息:WM_CREATE
,在创建一个可识别
窗口时,生成一个对象实例
,并用SubclassWindow
勾挂该实例
到目标窗口
,让该对象实例
去完成剩下的事情
.
总结一下:
1
,为每种可识别的窗口类
编写类,实现必要的消息处理及保存状态
;
2
,用勾挂函数
拦截WM_CREATE
消息,并创建对应的类实例
;
3
,通过SubclassWindow
操作把生成的类实例
勾挂到目标窗口
,处理消息
及保存状态
;
对PushButton
绘画的问题,我冒昧对你的代码做了点修改.思路就是在子类化按钮
后,将按钮
的风格
改成自绘画
,这样就不会和按钮
自身的绘画干扰了,而且我估计只要处理WM_DRAWITEM
和WM_MEASUREITEM
消息就可以了,不过我没有这么试过.
但是复选框
和RadioButton
没有BS_OWNERDRAW
风格,所以没法这么做.绘画干扰问题还没有解决.下面贴出我对CMacButton
修改过的地方:
1
,增加long m_iCtrlType;
成员变量
2
,
void Initialize(){m_iCtrlType=-1;//..m_nState = STATE_NORMAL;m_bTracking = false;if(BASETYPE_BUTTON==GetBaseType())//..{::SetWindowLong(m_hWnd,GWL_STYLE,::GetWindowLong(m_hWnd,GWL_STYLE)|BS_OWNERDRAW);}}
3,long GetBaseType(){if(m_iCtrlType!=-1)return m_iCtrlType;//..long lStyle = GetWindowLong(GWL_STYLE);if ( (lStyle & BS_OWNERDRAW) == BS_OWNERDRAW )//`物主画`return m_iCtrlType=BASETYPE_OWNERDRAW;//..if ((lStyle & BS_GROUPBOX)==BS_GROUPBOX)//组框return m_iCtrlType=BASETYPE_GROUPBOX;else if ((lStyle & BS_CHECKBOX)==BS_CHECKBOX|| (lStyle & BS_AUTOCHECKBOX) == BS_AUTOCHECKBOX )//复选框return m_iCtrlType=BASETYPE_CHECKBOX;else if ((lStyle & BS_AUTORADIOBUTTON)==BS_AUTORADIOBUTTON|| (lStyle & BS_RADIOBUTTON)==BS_RADIOBUTTON)//收音机return m_iCtrlType=BASETYPE_RADIOBUTTON;//普通按钮return m_iCtrlType=BASETYPE_BUTTON;}
这样,要为每种需要改变外观
的控件窗口
编写一个类
,很自然的想到取出它们的公共基类
,这就是CWidgetHookBase
,所有控件窗口
处理类的公共基类
,实际上是一个C++
接口,因为它只包含一个纯虚函数
,下面是它的定义
:
组件勾挂的抽象基类
class CWidgetHookBase
{
public:virtual void Install(HWND hWidget) = 0; //在`CWidgetHook`中实现
};
该接口
中唯一的安装
函数,用来实现把对象链接到窗口
的功能,也就是SubclassWindow
,这会在继承类
实现.
这里要讲的实际上是控件类工厂
,也就是CWidgetFactory
及其继承类
.下面是CWidgetFactory
的完整声明和实现
:
///用来勾挂`组件`的抽象工厂类.创建`勾挂`实例
class CWidgetFactory
{
protected:static CWidgetFactory* m_pInstance;
public://初化实例CWidgetFactory(){ATLASSERT(m_pInstance==NULL);m_pInstance = this;}//取单例实例static CWidgetFactory* Instance(){return m_pInstance;}virtual CWidgetHookBase* CreateWidget(LPCTSTR szClass) = 0;
};
CWidgetFactory* CWidgetFactory::m_pInstance = NULL;
CWidgetFactory
使用了两个设计模式
,单件
模式和抽象工厂
模式,实际上还包括抽象方法
模式.
首先看抽象工厂模式
,想让控件工厂
根据窗口类
的名字创建
出不同控件
的窗口消息处理类
.对仿真Mac
的系统,这些控件窗口消息处理类
包括CMacButton,CMacComboBox,CMacTrackBar
等;
而对仿真KDE
的系统,则是CKDEButton,CKDEComboBox
等.这样,就可定义
两个CWidgetFactory
的继承类,分别叫CMacFactory
和CKDEFactory
,分别产生这两个族的对象
.
CWidgetFactory::CreateWidget
就是用来产生这些对象
的方法,它是个必须在继承类中实现
的纯虚函数
.CreateWidget
接受窗口类
的名字为参数,返回所有控件类的基类
的CWidgetHookBase
指针.
这样,每个对象工厂
负责产生一族对象
,但对一个应用
来说,应该只有一个风格
,也即,只有一个工厂
的实例,单件模式
来了.
这里使用
简化版的单件
模式,需要声明一个继承类的实例
,然后通过CWidgetFactory
的实例
静态函数得到该唯一实例
.
这里没有控制
不能生成第二个实例
,不过问题不大.
现在来看工厂
的一个实现,CMacFactory
,完整的代码如下:
class CMacFactory : public CWidgetFactory
{
public:virtual CWidgetHookBase* CreateWidget(LPCTSTR szClass){if (lstrcmpi(szClass, "Button") == 0 )return new CMacButton;else if (lstrcmpi(szClass, "#32770") == 0) //对话return new CMacDialog;else if (lstrcmpi(szClass, "ListBox") == 0)return new CMacListBox;else if (lstrcmpi(szClass, WC_TABCONTROL) == 0)return new CMacTabCtrl;else if (lstrcmpi(szClass, "#32768") == 0) //菜单return new CMacMenu;else if (lstrcmpi(szClass, "ComboBox") == 0) //组合框return new CMacCombo;else if (lstrcmpi(szClass, TRACKBAR_CLASS) == 0) //跟踪杆return new CMacTrackBar;return NULL;}
};
再看看消息勾挂
的代码:
LRESULT CALLBACK CMacSkin::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{CWPSTRUCT cwps;if( nCode == HC_ACTION ){CopyMemory(&cwps, (LPVOID)lParam, sizeof(CWPSTRUCT));switch(cwps.message){case WM_CREATE:{CHAR szClass[MAX_PATH];GetClassName(cwps.hwnd, szClass, MAX_PATH);CWidgetHookBase* pWidget=NULL;pWidget = CWidgetFactory::Instance()->CreateWidget(szClass);if (pWidget)pWidget->Install(cwps.hwnd);}break;}}return CallNextHookEx((HHOOK)CMacSkin::m_hHook, nCode, wParam, lParam);
}
不管对CMacFactory
还是其他的工厂实现,及不同控件类族,勾挂函数
的实现都是一样的.CWidgetFactory
继承类的实现
也类似,只是替换一些类名而已.
现在,有了控件类的接口
:CWidgetHookBase
,产生控件对象的工厂
也有了,下面就该实现控件类
了.在定义控件基类
时,只定义了一个抽象
的安装
函数,而没有其他代码,则,所有实现代码
都交给各个控件类
去实现吗?
不是,这些控件类
还有许多公共代码
可在基类
实现,但是,选择不在CWidgetHookBase
中加入这些代码
,而是再加入一个中间类
:CWidgetHook
.
不可把这两个基类
合为一个类
呢?其实,最初的设计
是只有一个基类
的,就是CWidgetHook
,而又想在继承类
中使用WTL
包装窗口
控件的类,这样,根据ATL/WTL
的架构,CWidgetHook
就必须是一个模板类
,而模板类
是不能作为基类指针
的,因为模板是类型不定的,而抽象工厂模式
要求一个基类指针
,所以又取出CWidgetHookBase
此纯虚的接口类
.
下面是CWidgetHook
模板类的声明:
//`//`所有`组件`勾挂的基类/参数:`/T/`继承类`/TBase/Widget`窗口包装器,为了方便,使用`WTL`包装器template <class T, class TBase = CWindow>
class CWidgetHook : public CWidgetHookBase, public CWindowImpl<T, TBase>
//CRTP
这里用了多继承
,它也是ATL
里常用的,第一个父类
是前面
定义的CWidgetHookBase
接口,需要该接口
来实现抽象工厂设计模式
.
第二个父类
是CWindowImp
,这是ATL
定义的,是所有窗口类
的(虽然不是顶层)高层父类
.
CWindowImp
接收两个模板参数
,同时也是CWidgetHook
的模板参数
.第一个模板参数
是继承类
,这也是ATL
中常用的技巧,该技巧使得可在父类
中知道继承类的类型
,于是,把本
指针转换成继承类的类型
,就可调用继承类的方法
,这样实现了类似虚函数的多态
,却不需要付出虚函数的性能代价
.
追踪ATL
的代码,可见其实TBase
参数最终是作为基类
的,通过模板参数
改变基类,这也是模板
与OO
不同的地方.
TBase
有一个默认CWindow
值,可在此传入其他类
,但必须是CWindow
的继承类
,最有价值的参数
当然是WTL
窗口包装类,这样,在实现控件消息处理类
时,就可用WTL
包装类提供的功能
,而不需要
只依赖窗口接口
了,确实可带来不少帮助
.
讲完CWidgetHook
的声明.下面来看CWidgetHook
的定义和实现
,首先看几个函数声明
:
void Initialize() {}; //初化实例void Finalize() {}; //实例`终止器`static void InitializeClass() {}; //初化类static void FinalizeClass() {}; //类的`终止器`
上面四个函数
都包含了空的实现
,在继承类
中可选择
重载它们.
在生成每个实例
时,调用初化
,在析构实例
前,调用终止器
;在生成
类的第一个实例
时调用InitializeClass
静态函数,在析构类的最后实例
时调用FinalizeClass
.
为什么要有两个静态函数
呢,因为一个类
代表同一个窗口
,这些窗口
会使用同样的资源
,如复选框
,需要几张不同状态的图片
,而这些图片
对每个复选框
来说都是一样
的,如果为每个实例
保存这样一份资源
,就有点浪费
内存了.
对一个皮肤
插件来说,效率
还是很重要的,所以选择用静态变量
保存这些图片
,并在第一个生成复选框
时,加载这些资源
,后续
生成的其他复选框
可重用这些资源
,然后在最后复选框
消失时释放这些资源
,这样,最小化了内存的使用量
.
在构造器和析构器
中调用这两个静态函数
,另外还有个m_lRef
实例计数值,下面还剩下OnFinalMessage
和安装
函数没讲.
OnFinalMessage
比较简单,调用Finalize
并删除自己
,因为是CWindowImp
继承类,OnFinalMessage
函数会在析构窗口
时自动调用它,这样,就保证了会自动释放实例
,不会造成泄漏内存
.
最后看安装
函数,这是在CWidgetHookBase
中定义的纯虚函数
,在CWidgetHook
模板类中实现它
.
安装
函数的主要功能
是调用SubclassWindow
,从而控制窗口消息
.另外,还控制反射消息和初化实例
.
下面是它的代码
:
virtual void Install(HWND hWidget){ATLASSERT(::IsWindow(hWidget));SubclassWindow(hWidget);//如果它是子窗口,请为其父窗口安装一个`反射器`,这样`父窗口`会反射回消息给我if ( (::GetWindowLong(hWidget, GWL_STYLE) & WS_CHILD) == WS_CHILD){HWND hWndParent = ::GetParent(hWidget);ATLASSERT(::IsWindow(hWndParent));// `WM_GETREFLECTOR`取已安装的反射器(如果有)CReflectHook* pReflector =(CReflectHook*)::SendMessage(hWndParent, WM_GETREFLECTOR, 0, 0);if (!pReflector)new CReflectHook(hWndParent);}T* pT = static_cast<T*>(this);pT->Initialize();//继承类要实现.在此针对性的初化.}
安装
函数是模板方法,它调用的初化
方法则要在继承类
中重载.则,初化
方法是实例的初化函数
,不可放在构造器
里呢?
因为每个实例
的初化
可能不太一样
,要根据被勾挂的窗口
的状态决定
,所以,必须等到调用SubclassWindow
后,才调用初化
方法,在继承类
的初化
实现中,可通过m_hWnd
直接取得窗口句柄
,调用API
或WTL
包装类方法检查窗口状态
,并执行必要的实例初化代码
.
MFC
和ATL
都提供了反射消息
的机制,就是让父窗口
在收到这类消息
时,把它们再返回给控件窗口
,这就是反射消息
.
要实现皮肤
插件,也需要在控件窗口类
中收到这些消息
,但是,不能依赖ATL
或MFC
的反射,因为想可让不同主机程序
使用皮肤
插件,而不是局限于ATL
和MFC
.
其他程序
可能没有反射消息机制
,或使用了不同反射消息机制
.所以,实现了自己的反射消息机制
.
CReflectHook
类就是用来完成反射消息
的,其构造器
按参数接受父窗口的句柄
,然后调用SubclassWindow
把对象实例
链接到窗口
上去,这和控件
的实现类似.
ProcessWindowMessage
是个虚函数
,它的定义可追述到ATL
窗口类的最底层
,CReflectHook::ProcessWindowMessage
实现反射功能
,把收到
的需要反射的消息
返回给控件窗口
.
但也不是简单的原样返回
,而是包装成另一个WM_REFLECT
消息,以免和其他消息
冲突.当反射消息
发回给控件窗口
时,控件窗口
利用下面三个宏
展开WM_REFLECT
,并得到原消息
:
LF_REFLECTED_NOTIFY_CODE_HANDLER
LF_REFLECTED_COMMAND_CODE_HANDLER
LF_REFLECTED_MESSAGE_HANDLER
另外注意WM_GETREFLECTOR
消息,可用该自定义消息
来向父窗口
查询与其关联的CReflectHook
实例,以避免重复安装反射勾挂
,因为CReflectHook::ProcessWindowMessage
为该消息
返回了本
指针.
CWidgetHook::Install
使用了WM_GETREFLECTOR
消息.
最后说一下
怎么写CWidgetHook
继承类(即控件类
),这也是直接影响最终效果
的.WTL
定义了许多常见控件包装类
,把这些类
作为CWidgetHook
的第二个模板参数
,可以大大简化后续工作
,当然,如果没有对应的包装类
,也可接收默认参数
.
因为借助了ATL/WTL
的基本架构
,编写控件类
和写一个ATL
窗口类类似
,可用ATL/WTL
消息映射宏,当然,不象MFC
一样提供了向导
,需要手动输入这些宏
.
另外,控件类
还可选择的重载CWidgetHook
定义的4个初化和清理函数
.附带示例
中提供
了一个Mac
按钮类的实现,可参考,该按钮示例
算是比较复杂
的,因为窗口
窗口类名为"按钮"
的窗口,实际上包括普通按钮,单选钮和复选框
,其他的许多控件
实现起来比按钮
容易,当然也有一些比较麻烦
的.
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
2501wtl,皮肤技术
下载地址 设计目标 最重要的是使用方便,已有程序创建一个COM对象,调一个方法就可把界面外观全部改成Mac风格的. 另外一个目标是要有扩展性. 所以,基本设计是定义一个统一的接口,然后用不同实现.每一个实现单独放在一个COMDLL中,调用者选择一个类标创建对象就行了. 接口的定义…...
![](https://i-blog.csdnimg.cn/direct/f119060685f741a6a387a6291bc74c06.png)
【面试题】技术场景 6、Java 生产环境 bug 排查
生产环境 bug 排查思路 分析日志:首先通过分析日志查看是否存在错误信息,利用之前讲过的 elk 及查看日志的命令缩小查找错误范围,方便定位问题。远程 debug 适用环境:一般公司正式生产环境不允许远程 debug,多在测试环…...
![](https://i-blog.csdnimg.cn/direct/78663de962914887bf01d4503dfe87b1.png)
word论文排版常见问题汇总
word论文排版常见问题汇总 常用快捷键: Alt F9 正常模式与域代码模式切换 Ctrl F9 插入域代码 F9 刷新域代码显示,要注意选定后刷新才会有效果 word中在当前列表的基础上修改列表 在使用word时,我们会定义一个列表,并将其链接…...
![](https://i-blog.csdnimg.cn/img_convert/4927b3fcef1f3fcd0fa28dfe89eba285.png)
传奇3仿韩服单机版安装教程+GM管理面板
今天为大家带来一款怀旧网单《传奇3仿韩服》的游戏架设,适用于单机娱乐, 仅供怀旧,本人已经安装游戏成功,特此带来详细安装教程。 适用环境 单机 视频演示 传奇3仿韩服单机 亲测截图 架设步骤 关闭默认杀毒软件和其它自己下的杀…...
![](https://www.ngui.cc/images/no-images.jpg)
第26章 汇编语言--- 内核态与用户态
汇编语言是低级编程语言的一种,它与特定计算机的硬件架构紧密相关。内核态和用户态是操作系统中进程运行的两种不同模式,它们用来区分操作系统内核代码和其他应用程序代码的执行环境。下面我将简要解释这两种状态,并给出一个简单的示例来展示…...
![](https://i-blog.csdnimg.cn/direct/3a17d82c62144017801f7f6ee2dbb3f6.png)
Spring bean的生命周期和扩展
接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,以具体实例看bean生命周期的一些执行阶段 bean生命周期流程 生命周期扩展处理说明实例化:createBeanInstance 构造方法, 如Autowired的构造方法注入依赖bean 如UserSer…...
![](https://i-blog.csdnimg.cn/direct/eabe0a0ea552457cba7bce78b66fefc7.png)
计算机网络 (33)传输控制协议TCP概述
一、定义与基本概念 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它工作在OSI模型的第四层,即传输层,为用户提供可靠的、有序的和无差错的数据传输服务。TCP协议与UDP协议是传输层的两大主要协议,但两者在设计上有明显的不同&…...
![](https://www.ngui.cc/images/no-images.jpg)
Python3 JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript编程语言的一个子集,但JSON是独立于语言的,很多编程语言都支持JSON格式数据的…...
![](https://www.ngui.cc/images/no-images.jpg)
Leetcode 698 Partition to K Equal Sum Subsets
题意 给一个数组,要求把数组里的元素分成k个子集,满足每个子集中数的总和是相等的。问是否能分成k个子集 题目链接 https://leetcode.com/problems/partition-to-k-equal-sum-subsets/description/ 思考 想象你有k个桶,然后你有n个小球&…...
![](https://i-blog.csdnimg.cn/img_convert/04b8ae2d373626634d0606f24ef14dba.png)
可靠的人形探测,未完待续(III)
一不小心,此去经年啊。问大家新年快乐! 那,最近在研究毫米波雷达模块嘛,期望用在后续的产品中,正好看到瑞萨的活动送板子,手一下没忍住。 拿了板子就得干活咯,我一路火花带闪电,开整…...
![](https://www.ngui.cc/images/no-images.jpg)
Git文件夹提交错了,怎么撤销?
最近提交了一些不应该提交的文件夹到git中,现在需要移除它们,现在简单记录一下操作日志: 情况一 文件夹已经被添加到 Git,但未提交 如果文件夹已经被 git add 添加到暂存区中,但尚未提交,你可以使用以下命令将其从暂存区中移除: git rm -r …...
![](https://i-blog.csdnimg.cn/direct/5a9dde925810495699042595926a55fc.png)
小程序textarea组件键盘弹起会遮挡住输入框
<textarea value"{{remark}}" input"handleInputRemark" ></textarea> 如下会有遮挡: 一行代码搞定 cursor-spacing160 修改后代码 <textarea value"{{remark}}" input"handleInputRemark" cursor-spacin…...
![](https://www.ngui.cc/images/no-images.jpg)
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例 1.代码在/kernel-5.10文件夹下 2.在kernel-5.10目录下执行如下命令编译 : 编译之前,需要将 clang 导出到 PATH 环境变量: 如果是 Android12 执行下面这条命令 export PATH../pr…...
![](https://i-blog.csdnimg.cn/direct/29eacd711dc64a278b6934b3568ad2b9.png)
qt 窗口(window/widget)绘制/渲染顺序 QPainter QPaintDevice Qpainter渲染 失效 无效
qt窗体布局 窗体渲染过程 qt中窗体渲染逻辑顺序为 本窗体->子窗体/控件 递归,也就是说先渲染父窗体再渲染子窗体。其中子窗体按加入时的先后顺序进行渲染。通过下方的函数调用堆栈可以看出窗体都是在widget组件源码的widgetprivate::drawwidget中进行渲染的&am…...
![](https://i-blog.csdnimg.cn/direct/c68e5a01c0ab4c52ba104f8d55e35c90.png)
Ubuntu下载时不显示无线网图标并显示Cable unplugged
我用的是ubuntu22-04-5.iso一下载出来发现无法连接网络甚至直接显示Wired是Cable unplugged. 下面是解决方法: step1: step2:点击编辑中的虚拟网络编辑器 step3: step4: step5: step6:取消勾选自动检测可用的DNS服务器 step7:在window上按下winR输入c…...
![](https://img-blog.csdnimg.cn/direct/135b53b5f5c443c28858992462ee4c98.gif#pic_center)
微信小程序实现人脸识别登录
hello hello~ ,这里是 code袁~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 🦁作者简介:一名喜欢分享和记录学习的在校大学生…...
![](https://www.ngui.cc/images/no-images.jpg)
atoi函数的概念和使用案例
atoi 函数是 C 语言标准库中的一个函数,它用于将字符串转换为整数。atoi 的名称是 “ASCII to integer” 的缩写。该函数定义在 <stdlib.h> 头文件中。 概念 atoi 函数会从字符串的开始位置开始转换,直到遇到第一个非数字字符或遇到字符串结束符…...
![](https://i-blog.csdnimg.cn/direct/4a2ed23cbb4c4b5cbd4458be492590f7.png)
Mysql--运维篇--日志管理(连接层,SQL层,存储引擎层,文件存储层)
MySQL提供了多种日志类型,用于记录不同的活动和事件。这些日志对于数据库的管理、故障排除、性能优化和安全审计非常重要。 一、错误日志 (Error Log) 作用: 记录MySQL服务器启动、运行和停止期间遇到的问题和错误信息。 查看: 默认情况下…...
![](https://i-blog.csdnimg.cn/direct/346ad93737b343858a976c02373e11e5.png)
poi处理多选框进行勾选操作下载word以及多word文件压缩
一、场景 将数据导出word后且实现动态勾选复选框操作 eg: word模板 导出后效果(根据数据动态勾选复选框) 二、解决方案及涉及技术 ① 使用poi提供的库进行处理(poi官方文档) ② 涉及依赖 <!-- excel工具 --><depen…...
![](https://www.ngui.cc/images/no-images.jpg)
QT 键值对集合QMap
在QT中,可以使用QMap作为键值对的集合。QMap是Qt的一个模板类,它存储了键值对,并且可以通过键来快速查找值。 导入 #include <QMap> 以下是一些使用QMap的方法: 1.创建并初始化一个 QMap<int, QString> UserDepa…...
![](https://www.ngui.cc/images/no-images.jpg)
NetMQ里Push-Pull模式,消息隔一收一问题小记
问题: 本机环境下,在push端向pull端发送消息的过程中,发现同一个进程里的pusher和puller代码,可以准确地完成收发; 然而,将代码放在两个进程里,将pusher发送的消息从1计数,puller端竟…...
![](https://www.ngui.cc/images/no-images.jpg)
见微知著:Tripo 开创 3D 生成新时代
关于 VAST VAST 成⽴于 2023 年 3 ⽉,是⼀家致⼒于通⽤ 3D 大模型研发的 AI 公司,公司⽬标是通过打造⼤众级别的 3D 内容创作⼯具,建⽴ 3D 的 UGC 内容平台,让基于 3D 的空间成为⽤户体验、内容表达、提升新质⽣产⼒的关键要素。 2024 年初,VAST 推出数⼗亿参数级别的 3…...
![](https://www.ngui.cc/images/no-images.jpg)
消息队列与中间件:Java的秘密传输带
消息队列与中间件技术是分布式系统中的重要组件,它们主要解决应用耦合、异步消息处理、流量削峰等问题,并实现高性能、高可用、可伸缩和最终一致性的架构。 2.1 消息队列的基本概念 消息队列是一种应用程序间传递消息的技术,它允许应用程序发…...
![](https://i-blog.csdnimg.cn/direct/210427a20b09485ab29a9e667a5fffbf.webp#pic_center)
Bytebase 3.1.0 - 通过 Google / GitHub SSO 功能开放给专业版
🚀 新功能 支持在 PostgreSQL DML/DDL 工单中选择执行角色。 在项目设置中增加 PostgreSQL 数据库租户模式配置选项。 在数据库页面和 SQL 编辑器为 ORACLE 数据库展示 package 元数据。 支持为环境配置颜色,方便区分。 新增管理员可关闭数据导出…...
![](https://i-blog.csdnimg.cn/img_convert/11242184881f4510ab7113a687105f0d.png)
EdgeOne安全专项实践:上传文件漏洞攻击详解与防范措施
靶场搭建 当我们考虑到攻击他人服务器属于违法行为时,我们需要思考如何更好地保护我们自己的服务器。为了测试和学习,我们可以搭建一个专门的靶场来模拟文件上传漏洞攻击。以下是我搭建靶场的环境和一些参考资料,供大家学习和参考࿰…...
![](https://i-blog.csdnimg.cn/direct/ea8d1b258d3847ce8673fedd778bba6e.png)
k8s部署rocketmq踩坑笔记
给团队部署一个rocketmq4.8.0. k8s上部署的broker,注册到nameserver上是自己的pod ip,导致本机连接到的broker的pod ip,这个ip k8s集群外的机器是无法联通的。 nameserver上注册的是这个pod ipv4 尝试将broker的配置brokerIP1修改为注册到na…...
![](https://www.ngui.cc/images/no-images.jpg)
Docker 通过创建Dockerfile 部署Jar包
1、创建Dockerfile 首先确保centos 安装docker,参考docker安装-CSDN博客 自己找个目录来存放Dockerfile mkdir Dockerfile 2、vim Dockerfile # 使用 OpenJDK 17 基础镜像 FROM jre17:v1.0# 设置工作目录 WORKDIR /app# 暴露端口 EXPOSE 8093# 设置容器内日志目录…...
![](https://i-blog.csdnimg.cn/direct/c1847b87c57a40debfbfcdc5ee9c8314.png)
shell脚本练习
题目 1、编写一个shell 脚本,检测 /tmp/size.log 文件。如果存在,显示它的内容;不存在则创建一个文件,将创建时间写入。 2、编写一个shell 脚本,实现批量添加 20个用户,用户名为user1-20,密码为user 后面跟…...
![](https://i-blog.csdnimg.cn/blog_migrate/c6909aecbcc13d601e65c093ad0ee5d7.gif)
【计算机网络】lab4 Ipv4(IPV4的研究)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀计算机网络_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2.…...
![](https://www.ngui.cc/images/no-images.jpg)
Python Json格式数据处理
示例:查看和编辑 JSON 文件的 Python 程序 import json from pprint import pprintdef load_json(file_path):"""加载并解析 JSON 文件。:param file_path: JSON 文件路径:return: 解析后的 JSON 对象(字典或列表)"&quo…...
![](/images/no-images.jpg)
网站备案链接直接查看/全球搜索网站排名
JsDoc 如果你在写javascript,是否羡慕过C,JAVA的文档自动生成工具?是否希望自己的程序也能自动生成一份对应的文档,犹如java API文档一样呢?不要再羡慕了。jsdoc_toolkit.zip 一款强大的js doc生成工具已经能完成你所羡…...
![](/images/no-images.jpg)
国内个人网站设计欣赏/自助建站官网
"ORA-01654: 索引VGSM.AUDIT_DATA_I无法通过8192(在表空间KLDB中)扩展"1.有可能是索引表空间不够select sum(bytes/1024/1024) sizeMB from dba_free_space z where z.tablespace_nameKLDB还有400M的剩余空间 应该足够。但是通过查询发现是 se…...
wordpress写插件/网络营销最基本的应用方式是什么
前言 开门见山,开篇明意。这篇博客主要讲解一下Android中ProgressBar控件以及间接继承它的两个子控件SeekBar、RatingBar的基本用法,因为其有继承关系,存在一些共有特性,所以在一篇博客中讲解。下面先简单描述一下这三个控件&…...
![](/images/no-images.jpg)
炫彩发光字制作网站/广东网站se0优化公司
最近一直找java8相关新特性的文章,发现都太没有一个连贯性,毕竟大家写博客肯定都有自己的侧重点,这里找到一本书,专门介绍java8新特性的,感觉大家可以看看《写给大忙人看的JavaSE8》.这里我会结合书中的知识以及网上的…...
![](/images/no-images.jpg)
网站建设 长春/google推广 的效果
Python3.x 1 数据类型 1.0 标准数据类型 Python3.x标准数据类型有6中,如下: 序号数据类型描述1数字Number2字符串String3列表List4元组Tuple5字典Dictionary6集合Set 1.2 数字(Number) 数字包括整数,浮点数,布尔数据和复数四种,python3.x中将True和False定义成关键字,表示…...
![](https://img-blog.csdnimg.cn/img_convert/a6a744edd351cb3debff2687b84f11ac.png)
江苏企业网站定制服务/免费发外链
一、首先安装 MySQL1. 安装前更新一下仓库,输入命令:sudo apt-get updatealgerfanalgerfan:~$ sudo apt-get autoremove --purge mysql-server-5.72. 输入命令:sudo apt-get install mysql-server mysql-client安装MySQL数据库程序和命令行管…...