句柄到底是个什么玩意?

mummyII 2011-09-25 01:52:18
对于一个treeview来说,每一个item的句柄是固定的还是变化的?我想根据一个item的属性item.data查找该item的句柄从而定位这个item。看了几个例子都很麻烦。我就想如果句柄似乎固定的话,我在建立treeview的时候就把每一个item的句柄保存在一个数据库表里,这样就简单多了。那么是不是可以这么做呢?
...全文
359 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
yyoinge 2011-09-27
  • 打赏
  • 举报
回复
上面的步骤(5)用递归来实现比较简单,也好理解一些
yyoinge 2011-09-27
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 mummyii 的回复:]
由于我的数据量太大,每次打开时至形成了treeview的第一层,然后用itempopulate才得到并打开下一层(你知道的),这个函数也适用么?
[/Quote]

只要你单击了,响应了itempopulate,则我提供的方法可以找到itempopulate中新增的节点

但是如果某节点没有被单击响应过itempopulate事件,则它的子节点此时并没有被插入,即便它在数据库中是存在,也无法finditem

你可以用一个实例变量数据存储来存储ids_node树形控件已经生成了的节点的data属性、label属性、handle属性
(1)在树形控件初始化及触发itempopulate事件时,往数据存储ids_node里面插入尚未存在的node信息。
(2)每次查找时,先到ids_node中进行查找,找到则直接定位到handle所对应的节点; 找不到,则到数据库中查找。
(3)如果数据库中也找不到对应的数据,则表示查找的内容不存在,查找结束
(4)如果数据库中查找得到对应的数据,则接着在数据库中查找该数据对应的父数据(也就是该数据在树形控件中的节点对应的父节点),如果父数据存在与ids_node中(假设在ids_node中存储的handle为100),则可以通过强制触发itempopulate事件来及时添加子节点(tv_1.event itempopulate(100) ),添加完子节点后,再到ids_node中查找数据,找到则选中节点。
(5)注意,步骤(4)中查找父数据的过程,应该用循环来表示。比如有数据链:a → aa → aaa → aaaa ,其中a是最父亲级别的数据,aaaa是最子级的数据,如果要查找的数据是“aaaa”,它不存在于ids_node中,其父数据“aaa”也不存在于ids_node中,则需要再查找“aaa”的父数据“aa”,如果“aa”还是不存在于ids_node中,则需要再查找父数据“a”。如果“a”存在与ids_node中,则需要先勇“a”所在节点添加子节点(tv_1.event itempopulate(a对应handle)),然后再为“aa”所在节点添加子节点(tv_1.event itempopulate(aa对应handle)),知道“aaaa”对应的节点被添加,才选中“aaaa”所在节点。
(6)当ids_node的rowcount()等于数据库中的数据量时,则不再检索数据库,这样可以减少与数据库的交互次数
mummyII 2011-09-27
  • 打赏
  • 举报
回复
呵呵,大神都来了
路人甲cw 2011-09-27
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wlj768 的回复:]

顶一下,也被句柄搞糊涂,C#里什么类型就是什么类型,PB里能用数字代表某个东西,前段时间一直转不过弯来。
[/Quote]
Win32编程中句柄都是一样的,C#里只不过把它封装成了IntPtr类型,但实质上都是长整型数值,十进制表示对象的句柄地址
Samoon 2011-09-27
  • 打赏
  • 举报
回复
发现PB一提到Treeview就连大神都会出现了。一刷新句柄就会变的,所以判断data比较好。
wlj768 2011-09-26
  • 打赏
  • 举报
回复
顶一下,也被句柄搞糊涂,C#里什么类型就是什么类型,PB里能用数字代表某个东西,前段时间一直转不过弯来。
mummyII 2011-09-26
  • 打赏
  • 举报
回复
由于我的数据量太大,每次打开时至形成了treeview的第一层,然后用itempopulate才得到并打开下一层(你知道的),这个函数也适用么?
wag_enu 2011-09-26
  • 打赏
  • 举报
回复
句柄:
在TV 里,句柄handle 是每插入一 item 所返回的一个 long 型的数值。它是程序运行时产生的,根据item 插入的先后,依次计数。根据这个handle 就可以操作TV 的对应的ITEM 。

[Quote=引用 4 楼 mummyii 的回复:]
如果是用itempopulate才形成的treeview不能用这个把
[/Quote]
不管用什么方法构建的TV,只要像yyoinge 在3#那样 灵活应用finditem 方法和相关事件里的 handle ,都可以很方便的找到需要的节点。
mummyII 2011-09-26
  • 打赏
  • 举报
回复
如果是用itempopulate才形成的treeview不能用这个把
yyoinge 2011-09-25
  • 打赏
  • 举报
回复
f_tv_find 函数
global function long f_tv_find (treeview atv, string as_data, boolean ab_data, long al_handle_s, long al_handle_e);//===========================================================
// f_tv_find :在树atv中从句柄为al_handle_s的节点开始查找内容
// ( 当ab_data为true时, 查找节点的data属性值;
// 当ab_data为false时, 查找节点的label属性值)as_data,
// 当查找到句柄为al_handle_e的节点时还没有找到符合条件的节点,则停止查找并返回-1
// 当查找到符合条件的节点时,则返回该节点的句柄
// 当查找完整棵树,未找到符合条件的节点,且未被中止时,则返回0
//===========================================================
if al_handle_s <= 0 then return 0
long ll_h
treeviewitem lt_tvi
if atv.GetItem(al_handle_s, lt_tvi) = -1 then return -1
if ab_data then //查找data
if (Not IsNull(lt_tvi.data)) and (string(lt_tvi.data) <> "") then
if lt_tvi.data = as_data then return al_handle_s
end if
else//查找label
if lt_tvi.label = as_data then return al_handle_s
end if
if al_handle_s = al_handle_e then return -1 //强制中止查找
al_handle_s = atv.FindItem(ChildTreeItem!, al_handle_s)

do while al_handle_s > 0
ll_h = f_tv_find(atv,as_data,ab_data,al_handle_s,al_handle_e)
if ll_h = -1 or ll_h > 0 then return ll_h //强制中止或者找到节点,则直接返回
//查找下一个兄弟节点
al_handle_s = atv.FindItem(NextTreeItem!, al_handle_s)
loop
//没有找到,则返回0
return 0
end function


在tv_1中从根节点开始查找label内容为“明细备注”的第一个节点
long ll
ll = f_tv_find(tv_1,'明细备注',false, tv_1.FindItem(RootTreeItem!, 0), 0)


在tv_1中从根节点开始查找data内容为“明细备注”的第一个节点
long ll
ll = f_tv_find(tv_1,'明细备注',true, tv_1.FindItem(RootTreeItem!, 0), 0)


在tv_1中从句柄为5的节点开始查找data内容为“明细备注”的第一个节点
long ll
ll = f_tv_find(tv_1,'明细备注',true, 5, 0)


在tv_1中的节点5到节点20之间查找data内容为“明细备注”的第一个节点
long ll
ll = f_tv_find(tv_1,'明细备注',true, 5, 20)
路人甲cw 2011-09-25
  • 打赏
  • 举报
回复
句柄在一个应用程序实例中是固定的,但如果你将这个实例关闭再打开可能就会发现变化,因为这是操作系统分配给应用程序的,他实质上是对指针的一种系统级的封装,在API编程中调用者不需要知道对象的指针地址只需要知道对象句柄就可以了,系统会根据句柄去调用它指向的指针地址,因为指针可能由系统动态改变它所指向的内存区域,但句柄并不会改变而是更新它所指向的指针地址,此时对于调用者来讲并没有发生改变.而句柄的作用就是用于间接定位内存中的对象,当对象被释放时句柄也会被释放,所以下次再创建同一类型的对象时它的句柄可能就不会再是上一次创建时的句柄了,因为它可能已经被分配给其它对象了.
yyoinge 2011-09-25
  • 打赏
  • 举报
回复
句柄是控件的ID号,就想我们人的身份证号一样

不过treeviewitem的handle其实是有规律的,率先被insert的handle为1,后面被insert的依次加1递增

但是你的想法是无法实现的,因为handle不是固定的
一:SSDT表的hook检测和恢复 ~!~~~ 二:IDT表的hook检测和恢复 ~~~~~~(idt多处理器的恢复没处理,自己机器是单核的,没得搞,不过多核的列举可以) 三:系统加载驱动模块的检测 通过使用一个全局hash表(以DRIVEROBJECT为对象)来使用以下的方法来存储得到的结果,最终显示出来 1.常规的ZwQuerySystemInformation来列举 2通过打开驱动对象目录来列举 3搜索内核空间匹配驱动的特征来列举(这个功能里面我自己的主机一运行就死机,别的机器都没事,手动设置热键来蓝屏都不行,没dump没法分析,哎,郁闷) 4从本驱动的Modulelist开始遍历来列举驱动 四:进程的列举和进程所加载的dll检测 采用以下方法来列举进程: 1ZwQuerySystemInformation参数SystemProcessesAndThreadsInformation来枚举 2进程EPROCESS 结构的Activelist遍历来枚举 3通过解析句柄表来枚举进程 4通过Handletablelisthead枚举进程 5进程创建时都会向csrss来注册,从这个进程里面句柄表来枚举进程 6通过自身进程的HANDLETABLE来枚举进程 7通过EPROCESS的SessionProcessLinks来枚举进程 8通过EPROCESS ---VM---WorkingSetExpansionLinks获取进程 9暴力搜索内存MmSystemRangeStart以上查找PROCESS对象 进程操作: 进程的唤醒和暂停通过获取PsSuspendProcess和PsResumeProcess来操作的 进程结束通过进程空间清0和插入apc。 采用以下方法查找DLL: 1遍历VAD来查找dll 2挂靠到对应的进程查找InLoadOrderLinks来枚举dll 3暴力搜索对应进程空间查找pe特征来枚举dll DLL的操作: Dll的卸载是通过MmUnmapViewOfSection和MmmapViewOfSection(从sdt表中相应函数搜索到的)来实现的(本来想直接清0 dll空间,有时行有时不行)(只要将这个进程的ntdll卸载了,进程就结束了,一个好的杀进程的办法撒,绿色环保无污染),注入dll使用的是插入apc实现的。(注入的dll必须是realse版的。Debug版会出现***错误,全局dll注入貌似也是)插入apc效果不是很好,要有线程有告警状态才执行。 五:线程信息的检测 遍历ThreadList来枚举线程 线程的暂停和唤醒都是通过反汇编获取PsResumeThread和PsSuspendThread直接从r3传来ETHREAD来操作的,通过插入APC来结束线程 六:shadow sdt表的hook检测与恢复 没有采用pdb来解决函数名问题,直接写入xp和03的shandow表函数名(主要是自己的网不稳定,连windbg有时都连不上微软) 七:系统所有的过滤驱动的检测 查看各device下是否挂接有驱动之类的,可直接卸载 八:系统常用回调历程的检测和清除 只检查了PsSetLoadImageNotifyRoutine PsSetCreateThreadNotifyRoutine PsSetCreateProcessNotifyRoutine CmRegisterCallback这几个,至于那个什么shutdown回调不知道是啥玩意,就没搞了,有知道的顺便告诉我下撒,谢谢 九:文件系统fat和ntfs的分发函数检测 直接反汇编fat和ntfs的DriverEntry得到对应的填充分发的偏移,然后和当前已经运行的文件系统的分发相比是否被hook,并附带恢复 十:文件查看功能 自己解析ntfs和fat的结构,来实现列举文件和直接写磁盘删除。附带有普通的删除和发生IRP来删除。不过这里面有点问题,ntfs删除有时把目录给搞坏了,大家凑合着吧, Ntfs网上删除这些操作的代码不多,就是sudami大大的利用ntfs-3g来实现的,看了下,太多了,充满了结构。然后自己对照着系统删除文件时目录的变化来自己实现的。只处理了$BITMAP对应的位清除,父目录的对应文件的索引项的覆盖,删除文件对应的filerecord清0. 另外偷懒时间都没处理,呵呵,y的,一个破时间都都搞好几个字节移来移去的。 十一:常用内核模块钩子的检测和恢复 这里只检测了主要的内核模块nkrnlpa**.exe的.win32k.sys,hal.dll,比对它们的原始文件从而查找eat inline hook,iat hook ,和inline hook。Inline是从TEXT段开始一段位置开始比较的。(有点慢貌似,等待显示扫描完成就好了) 十二:应用层进程所加载dll的钩子 应用层钩子检测和内核模块钩子检测原理一样,不过为了能读写别的进程的空间,并没有使用openprocess去打开进程,而是通过KiattachProcess挂靠到当前进程,然后通过在r0直接读写进程空间的。

604

社区成员

发帖
与我相关
我的任务
社区描述
PowerBuilder 控件与界面
社区管理员
  • 控件与界面社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧