浅谈FromHandle

CWnd的常用成员函数 1.有句柄转为CWND对象 (1)FromHandle和GetGlgItem:产生一个临时性窗口指针,只限于在当前函数内使用; (2)Attach和Detach成对使用为一个CWnd对象嫁接和移除窗口句柄。只用attach在摧毁窗口时会出现错误; (3)SubclassWindow和UnSubclassWindow,子类化和反子类化,还能通过子类接收窗口消息; (4)SubclassDlg 阅读详情
你的程序中必然对你的主窗口Attach(这是由Framework完成的),这样的话,假如你又得到了你程序的主窗口句柄hwndMain,你如果再调用FromHandle(hwndMain),它返回的将是你的App中的m_pMainWnd,原因就是FromHandle会维持一个内部的列表,纪录每个hwnd与CWnd的关联情况,如果一旦一个hwnd早已与某个CWnd对象相关连,它会返回该CWnd对象的指针。既然如此,FromHandle返回的便是m_pMainWnd,而此对象Framework会自动析构,因此你只是得到了该指针的一个副本,不能对其作析沟操作,否则会导致你的程序运行不正常。 
   考虑另外一种情况,就是一个hwnd与任何对象都没有关联(比如,你用API CreateWindow新建了一个窗口),此时的hwnd尚未与任何CWnd对象关联,如果你用FromHandle(hwnd),FromHandle便会临时new一个CWnd对象,并Attatch到此hwnd,然后返回给你。我刚才说了,FromHandle会维持一个hwnd与CWnd关联的列表,每当Framework OnIdle时,它便会检查此列表,一旦发现某个CWnd是FromHandle临时创建的对象,它便会首先Detach此对象,然后delete之。因此,你在程序中也不必delete从FromHandle得到的对象指针,但这种指针只在一次消息处理过程中有效。 
   另外还有FromHandlePermanent函数,它当且仅当hwnd已与某个CWnd对象关联时才返回此对象的指针,否则返回NULL。这也是它为什么叫Permanent——区别于FromHandle会new一个临时的CWnd对象。 
   对于GDI对象,以上的分析也是适用的。 

   另外,以上只是一种比较抽象的理解,具体MFC的实现,你看一下MFC的源代码,应该会有很大的帮助(MFC公开源代码,真是太好不过了)。

CBitmap::FromHandle

static CBitmap* PASCAL FromHandle( HBITMAP hBitmap );

返回值:调用成功时返回一个指向CBitmap对象的指针,否则返回NULL。

参数:

hBitmap指定一个Windows GDI 位图的句柄。


说明:
本函数在调用时指定一个Windows GDI 位图的句柄,返回一个指向CBitmap对象的指针。如果该句柄上没有相联系的CBitmap对象,则为该句柄建立一个临时CBitmap对象。该临时CBitmap对象保持有效,直到应用在它的事件循环中出现空闲时间,此时Windows会删除所有的临时图形对象。换句话说,临时对象仅在一个Windows消息的处理过程中有效。

MFC 对 Windows API 进行了封装,在很多方面都会提供便利。用 FromHandle 返回零时对象的指针,就可以调用各种类的方法。临时对象会在 OnIdle 中销毁。这里对 FromHandle 的实现原理从源码上进行解析。

// 
// 1 
// 
CWnd* PASCAL CWnd::FromHandle(HWND hWnd) 
{ 
    CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist 
    ASSERT(pMap != NULL); 
    CWnd* pWnd = (CWnd*)pMap->FromHandle(hWnd); 
#ifndef _AFX_NO_OCC_SUPPORT 
    pWnd->AttachControlSite(pMap); 
#endif 
    ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd); 
    return pWnd; 
}

这是 CWnd 的 FromHandle 方法,大致的意思为从 CHandleMap 中获取临时 CWnd 对象的指针。

// 
// 2 
// 
CHandleMap* PASCAL afxMapHWND(BOOL bCreate) 
{ 
    AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); 
    if (pState->m_pmapHWND == NULL && bCreate) 
    { 
        BOOL bEnable = AfxEnableMemoryTracking(FALSE); 
#ifndef _AFX_PORTABLE 
        _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler); 
#endif


        pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd), 
            offsetof(CWnd, m_hWnd)); 
#ifndef _AFX_PORTABLE 
        AfxSetNewHandler(pnhOldHandler); 
#endif 
        AfxEnableMemoryTracking(bEnable); 
    } 
    return pState->m_pmapHWND; 
}

再看

#define offsetof(s,m)   (size_t)&(((s *)0)->m)

继续

// 
// 3 
// 
CObject* CHandleMap::FromHandle(HANDLE h) 
{ 
    ASSERT(m_pClass != NULL); 
    ASSERT(m_nHandles == 1 || m_nHandles == 2);

    if (h == NULL) 
        return NULL;

    CObject* pObject = LookupPermanent(h); 
    if (pObject != NULL) 
        return pObject;   // return permanent one 
    else if ((pObject = LookupTemporary(h)) != NULL) 
    { 
        HANDLE* ph = (HANDLE*)((BYTE*)pObject + m_nOffset); 
        ASSERT(ph[0] == h || ph[0] == NULL); 
        ph[0] = h; 
        if (m_nHandles == 2) 
        { 
            ASSERT(ph[1] == h || ph[1] == NULL); 
            ph[1] = h; 
        } 
        return pObject;   // return current temporary one 
    }

    // This handle wasn't created by us, so we must create a temporary 
    // C++ object to wrap it.  We don't want the user to see this memory 
    // allocation, so we turn tracing off.

    BOOL bEnable = AfxEnableMemoryTracking(FALSE); 
#ifndef _AFX_PORTABLE 
    _PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler); 
#endif

    CObject* pTemp = NULL; 
    TRY 
    { 
        pTemp = m_pClass->CreateObject(); 
        if (pTemp == NULL) 
            AfxThrowMemoryException();

        m_temporaryMap.SetAt((LPVOID)h, pTemp); 
    } 
    CATCH_ALL(e) 
    { 
#ifndef _AFX_PORTABLE 
        AfxSetNewHandler(pnhOldHandler); 
#endif 
        AfxEnableMemoryTracking(bEnable); 
        THROW_LAST(); 
    } 
    END_CATCH_ALL

#ifndef _AFX_PORTABLE 
    AfxSetNewHandler(pnhOldHandler); 
#endif 
    AfxEnableMemoryTracking(bEnable);

    // now set the handle in the object 
    HANDLE* ph = (HANDLE*)((BYTE*)pTemp + m_nOffset);  // after CObject 
    ph[0] = h; 
    if (m_nHandles == 2) 
        ph[1] = h;

    return pTemp; 
}



转自:http://tsing01.blog.163.com/blog/static/205957283201242454821675/

           http://blog.youkuaiyun.com/huys03/article/details/4549678  

PyTorch生成式人工智能——VQ-VAE详解与实现 VQ-VAE (Vector Quantised-Variational AutoEncoder) 的核心思想就是将 VAE 的连续潜变量离散化。它通过学习一个码本 (Codebook) 来实现这一点,码本是一个包含有限个嵌入向量的字典。模型不是直接输出一个连续的潜在向量,而是从码本中找出与编码器输出最接近的嵌入向量来代替它。本节首先详细讲解 VQ-VAE 的技术原理,然后使用 PyTorch 从零开始实现 VQ-VAE 模型。 阅读详情

相关推荐

STM32+EC800M-CN 4G模块数据透传踩坑实录:从AT指令调试到花生壳内网穿透

本文详细介绍了STM32与移远EC800M-CN 4G模块的数据透传实现过程,包括硬件连接、AT指令调试、TCP连接建立以及花生壳内网穿透配置。通过实战案例和代码示例,帮助开发者快速解决4G通信模块在物联网应用中的常见问题,提升数据传输稳定性。

weixin_42715608的博客 322

FromHandle函数

一 FromHandle()   MFC 实际上是对内核对象HANDLE(如CDC的m_hDC,CWnd的m_hWnd)封装了这个句柄有关的所有操作,一个类生成一个新对象的时候这个句柄是无效的,要获得这个句柄,可以有两个方法,一个是Create来创建,另一个就是用Attach来与一个已有的句柄建立关联,实际上也就是给类的句柄成员变量赋值。 而有些时候这个句柄不是由我们创建,但是我们要对它的封装类进行操作,(mfc框架)必需创建对应的封装类包装它。 MFC 中对各种包含内核对象的封装类都有FromHan.

顺其自然~专栏 1797

CAN开发笔记(TI开发者推荐笔记)

查阅了很多资料没有查阅到关于5728芯片CAN模块寄存器的介绍,希望通过本文能给做CAN驱动的后来者有一点参考意义,我也是刚接触CAN模块有些不足请各位多多指正。 由下图所示是CAN模块初始化流程图 首先要开始初始化,设置CAN位时间,然后配置message objects, 完成初始化。 1.开始初始化 首先要控制DCAN_CTL 寄存器,该寄存器是CAN模块的总控制器,很多配置通过...

weixin_44316996的博客 3563

FromHandle 详解

FromHandle给出一个window对象句柄,返回一个相应对象的指针 如:CBrush::FromHandle static CBrush* PASCAL FromHandle( HBRUSH hBrush ); CFont::FromHandle static CFont* PASCAL FromHandle( HFONT hFont ); 转载于:https://www.cnbl...

weixin_34319111的博客 711

GD32F303 ADC+DMA实战:用硬件过采样搞定多通道数据采集(附完整代码)

本文详细介绍了GD32F303系列MCU通过ADC+DMA结合硬件过采样技术实现多通道数据采集的实战方案。从硬件设计要点到软件配置全解析,包括时钟树配置、ADC模块初始化和DMA传输设置,提供了完整的代码示例和优化技巧,帮助工程师构建高精度、低功耗的数据采集系统。

weixin_30466039的博客 320

NX二次开发入门必看:手把手教你搭建开发环境

想顺利开展nx二次开发,第一步就是配置好开发环境。本文详细讲解从安装准备到环境调试的完整流程,结合实际操作细节,帮你避开常见坑点,快速进入nx二次开发的实战阶段。

weixin_31569663的博客 1458

MFC-核心类库-CWnd的成员函数介绍(二)

1、CWnd :: FromHandleCWnd在给定窗口句柄时,返回指向对象的指针。如果CWnd对象未附加到句柄,CWnd则会创建并附加临时对象。static CWnd * PASCAL FromHandle(HWND hWnd);2、CWnd::Attach当我们使用MFC创建一个窗口时,是分两步进行的:第一步,new一个CWnd对象,这一步是创建C++对象,但是其中的HWND还是非法的,因为...

huanhuanxiaoxiao的博客 1001

ADS交叉耦合振荡器VCO仿真

本文主要参考视频中如何使用进行ADS交叉耦合振荡器仿真和分析,由于视频中有诸多错误和视频清晰度较低,虽然视频博主及时改正,为了节省学习时间,可以直接参考本文。

qq_32589131的博客 5427

MFC第十五天 HWND与CWnd对象之间的转换、CWnd类简介(补充)、员工管理系统登录界面眼睛捕获(补充)

HWND 与CWND 对象之间的转换,以及CWnd类的简介,对Setcapture捕捉函数以及相关函数进行介绍

Jcrry的博客 1829

深入解析ViT中的RoPE旋转位置编码:原理、实现与视觉应用

本文深入解析了ViT中的RoPE旋转位置编码原理、实现及其在视觉任务中的应用。RoPE通过旋转变换巧妙地将相对位置信息融入注意力计算,解决了传统绝对位置编码外推性差的问题,在图像分类、目标检测及生成任务中展现出更优的泛化能力和灵活性。

alice7model的博客 706

数学建模算法案例精讲500篇-【深度强化学习】深度确定性策略梯度(DDPG)(附MATLAB和python代码实现)

它是一种学习连续动作的无模型策略算法。它结合了DPG(确定性策略梯度)和DQN(深度Q网络)的思想。它利用DQN中的经验重放和延迟更新的目标网络,并基于DPG,可以在连续的动作空间上运行。# 用于生成带有噪声的动作def __init__(self, action_space, mu=0.0, theta = 0.15, max_sigma = 0.3, min_sigma = 0.3, decay_period = 100000):#decay_period要根据迭代次数合理设置# 均值 mu。

qq_36130719的博客 325

VC+MFC 浅谈FromHandle

介绍FromHandle是如何工作的,希望能加深你的理解。     例如,你的程序中必然对你的主窗口Attach(这是由Framework完成的),这样的话,假如你又得到了你程序的主窗口句柄hwndMain,你如果再调用FromHandle(hwndMain),它返回的将是你的App中的m_pMainWnd,原因就是FromHandle会维持一个内部的列表,纪录每个hwnd与CWnd的关联情况,

1586

C#实现将DataGridView中数据导出到Excel (附完整源码)

C#实现将DataGridView中数据导出到Excel (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1589

解析 MFC 中的 FromHandle

MFC 对 Windows API 进行了封装,在很多方面都会提供便利。用 FromHandle 返回零时对象的指针,就可以调用各种类的方法。临时对象会在 OnIdle 中销毁。这里对 FromHandle 的实现原理从源码上进行解析。// // 1 // CWnd* PASCAL CWnd::FromHandle(HWND hWnd) {

独木专栏 1万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

GetDlgItem

转自http://blog.youkuaiyun.com/loveghb/archive/2005/06/21/399784.aspx由GetDlgItem函数想到的 我们在调用CWnd::GetDlgItem()函数时,MSDN告诉我们:The returned pointer may be temporary and should not be stored for later use. 中文意...

weixin_30379973的博客 477

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

CDC类的Attach和FromHanle的区别

说她们的区别之前,先上段代码。。。 双缓冲绘图 void DoubleBufferDraw(HDC hDC) { CDC* pDC = new CDC; pDC->Attach(hDC); // do not use FromHanle CDC memDC; CBitmap memBitmap; memDC.CreateCompatibleDC(pDC); // break mem

lniwn 3782

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

VC中窗口ID,句柄,指针三者相互转换函数

ID--HANDLE--HWND三者之间的互相转换 id->句柄 hWnd = ::GetDlgItem(hParentWnd,id); id->指针 CWnd::GetDlgItem(); 句柄->id id = GetWindowLong(hWnd,GWL_ID); 句柄->指针 CWnd *pWnd=CWnd::FromHandle(hWnd); 如:CEpdscDlg* pdlg=(CEpdscDlg*)CWnd::FromH...

ctrigger的专栏 542

MFC获取各个窗口(体)之间的指针(对象)

MFC在很多的对话框操作中,我们经常要用到在一个对话框中调用另一个对话框的函数或变量.可以用如下方法来解决.    HWND hWnd=::FindWindow(NULL,_T("Sphere"));      //得到对话框的句柄    C***Dialog* pWnd= (C***Dialog*)C***Dialog::FromHandle(hWnd); //由句柄得到对话框的对象指针

Guo_guo 2万+

C++ 遍历寻找指定进程,通过进程ID获取窗口句柄,以及HWND与CWnd之间转换

问题: 如题,如何遍历寻找指定进程?如何通过进程ID获取窗口句柄?HWND与CWnd之间是如何转换的? 解决: 1、HWND与CWnd之间的转换:使用 GetSafeHwnd 和 CWnd::FromHandle // 已知 CWnd 获取 HWND CWnd* pCWnd; HWND hwnd = pCWnd->m_hWnd; HWND hwnd1 = pCWnd->GetSafeHwnd(); // 已知 HWND 获取 CWnd HWND hwnd2; CWnd* pCwnd1 = CW

m0_43605481的博客 4714

CWnd::FromHandle与CWnd::FromHandlePermanent有什么区别

你可以参考 MFC 代码中 FromHandle 和 FromHandlePermanent 的实现,这两个函数都是在公共的 CMapHandle 中查找句柄对应的 CWnd 对象(通过一个CBT钩子,CWnd 对象将创建时得到的句柄和自己的指针纪录到 CMapHandle),区别是如果找不到相关的对象,FromHandle 在CMapHandle 的 temporarylist 中创建并返回一个

Beyond.cn 6165

FromHandle与Attach。

通过HDC句柄创建CDC类,有两个方法,一个是FromHandle,一个是Attach。 FromHandle用于创建一个临时对象(类),没有独占性,MSDN上的说法是“临时的瞬态对象,不应在外部存储使用”,这种方法消耗小,通常用于临时绘制并且不改变DC属性的情况下。 Attach是一个独占的强制方法,创建一个长期使用的对象,通过Map的SetPermanent函数,完成了对象和句柄的捆绑,在释放

mfmfmmf1的专栏 1144

详细介绍CDC::FromHandle()

书籍:《Visual C++ 2017从入门到精通》的4.2 按钮控件环境:visual studio 2022内容:[例 4.2]制作图片按钮说明:以上内容大部分来自腾讯元宝。在 MFC 中,是连接 Windows 原生设备上下文(HDC)与 MFC设备上下文类(CDC)的核心接口。

felicity_one的博客 1148

MFC 常见窗口操作

1、改变窗口大小或全屏窗口可用下面的代码: MoveWindow(hDlg,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),TRUE);   2、去掉窗口的边框可用下面的代码: LONG nStyle= GetWindowLong( hDlg, GWL_STYLE); LONG newStyle=

逍遥子曰: 2785

CHandleMap::RemoveHandle(HANDLE h) 内断言报错

在做多线程的时候出现的错误,其实问题是出在别的地方。下面时出现的断言错误的地方 原错误代码: //绘制绿球 if (m_Isgreenball) { CDC *pDC = m_greenrect.GetDC(); CBrush *poldbrush; CBrush newbrush(RGB(0,255,0)); poldbrush=pDC->SelectObject(&...

XiaZai2510的博客 367

CMenu::FromHandle

返回指向 CMenu 对象提供Windows句柄菜单。 static CMenu* PASCAL FromHandle( HMENU hMenu ); 参数 返回值 这样可以是临时或永久的 CMenu 的指针。 备注

heary29的专栏 1272

FromHandle与FromChildHandle的区别

我在使用PropertyControl插件的时候,经常遇到一个问题,就是无法用窗口探测器探测到WebBrowser,原因很简单,探测到的句柄本身并不是Control对象,可能是它的一个子控件,而这个控件并没有封装成System.Windows.Forms.Control对象,所以解决办法是:如果FromHandle返回null,则继续枚举其父控件,只到找到为止,本来想自己写的,无意中发现了Fr

872
上一篇: CImageList
下一篇: OnCreate()和PreCreateWindow()函数的区别
heary29
博客等级 码龄12年 37粉丝 85原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值