• Windows_COM编程


    本文参考:https://blog.csdn.net/wangqiulin123456/article/details/8026270

    引言:

    在使用Qt在windows系统上编程的时候遇到了调节电脑亮度的Api,通过上网查找,发现这个功能依靠的是com相关的Api实现的。于是想了解一下什么是com编程。

    知识讲解:

    COM(组件对象模型)是Component Object Model的缩写。
    常见的术语:COM对象、接口、服务器等。
    COM编程的目的是通过二进制的方式来实现代码重用,但是在windows外很少听说。

    基本定义

    Com编程提供的都是接口,这些接口也被叫做方法。接口可以从其它接口继承,这里所说的继承的原理就好像C++中的单继承。接口是不允许多继承的。

    • coclass(简称组件对象类――componentobject
      class)被包含在DLL或EXE中,并且包含着一个或者多个接口的代码。组件对象类(coclasss)实现这些接口。COM对象在内存中表现为组件对象类(coclasss)的一个实例。注意COM“类”和C++“类”是不相同的,尽管常常COM类实现的就是一个C++类。
    • COM服务器是包含了一个或多个coclass的二进制(DLL或EXE)。
      注册(Registration)是创建注册表入口的一个过程,告诉Windows
      操作系统COM服务器放在什么位置。取消注册(Unregistration)则相反――从注册表删除这些注册入口。
    • GUID(谐音为“fluid”,意思是全球唯一标示符――globally unique identifier)是个128位的数字。它是一种独立于COM编程语言的标示方法。每一个接口和coclass有一个GUID。因为每一个GUID都是全球唯一的,所以避免了名字冲突(只要你用COM
      API创建它们)。有时你还会碰到另一个术语UUID(意思也是全球唯一标示符――universally unique
      identifier)。UUIDs和GUIDs在实际使用时的用途是一样的。
    • 类ID或者CLSID是命名coclass的GUID。接口ID或者IID是命名接口的GUID。

    使用:

    1. 创建COM对象并从这个对象获得接口:
      必须调用COM库的API函数,CoCreateInstance()。调用CoCreateInstance()时,它负责在注册表中查找COM服务器的位置,将服务器加载到内存,并创建你所请求的coclass实例。
    hr = CoCreateInstance ( 
    CLSID_ShellLink,         //coclass 的CLSID
    NULL,                    //不是用聚合
    CLSCTX_INPROC_SERVER,    //服务器类型
    IID_IShellLink,          //接口的IID
    (void**)&pISL );        // 指向接口的指针
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 删除/释放COM
      如果你的应用程序要长时间运行,就应该在应用程序处于空闲期间调用CoFreeUnusedLibraries() API。这个API将卸载任何没有明显引用的COM服务器。如果确实需要释放可以调用release。

    基本接口(IUnknown)所有的com都必须调用。
    单接口调用:

    步骤:
    1. 初始化COM库。 (Initialize);
    2. 创建一个与活动桌面交互的COM对象,并取得IActiveDesktop接口;
    3. 调用COM对象的GetWallpaper()方法;
    4. 如果GetWallpaper()成功,则输出/显示墙纸文件名;
    5. 释放接口(Release());
    6. 收回COM库(Uninitialize);
    {
        WCHAR   wszWallpaper [MAX_PATH];
        CString strPath;
        HRESULT hr;
        IActiveDesktop *pIAD;
    // 1. 初始化COM库(让Windows加载DLLs)。通常是在程序的InitInstance()中调用
    // CoInitialize ( NULL )或其它启动代码。MFC程序使用AfxOleInit()。
        CoInitialize ( NULL );
    // 2. 使用外壳提供的活动桌面组件对象类创建COM对象。
    // 第四个参数通知COM需要什么接口(这里是IActiveDesktop).
        hr = CoCreateInstance ( CLSID_ActiveDesktop,
                                NULL,
                                CLSCTX_INPROC_SERVER,
                                IID_IActiveDesktop,
                                (void **) &pIAD );
        if (SUCCEEDED(hr)) {
            // 3. 如果COM对象被创建成功,则调用这个对象的GetWallpaper() 方法。
            hr = pIAD->GetWallpaper(wszWallpaper, MAX_PATH, 0);
            if (SUCCEEDED(hr)) {
                // 4. 如果 GetWallpaper() 成功,则输出它返回的文件名字。
                // 注意这里使用wcout 来显示Unicode 串wszWallpaper. wcout 是
                // Unicode 专用,功能与cout.相同。
                wcout << L"Wallpaper pathis:\n    " << wszWallpaper << endl << endl;
            } else {
                cout << _T("GetWallpaper()failed.") << endl << endl;
            }
            // 5. 释放接口。
            pIAD->Release();
        } else {
            cout << _T("CoCreateInstance()failed.") << endl << endl;
        }
    // 6. 收回COM库。MFC 程序不用这一步,它自动完成。
          CoUninitialize();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    多接口COM:

    步骤:
    1. 初始化 COM 库;
    2. 创建一个用于建立快捷方式的COM 对象并取得IShellLink 接口;
    3. 调用IShellLink 接口的SetPath()方法;
    4. 调用对象的QueryInterface()函数并取得IPersistFile接口;
    5. 调用IPersistFile 接口的Save()方法;
    6. 释放接口;
    7. 收回COM库;
    
    {
        CString sWallpaper = wszWallpaper;  // 将墙纸路径转换为ANSI
        IShellLink   *pISL;
        IPersistFile *pIPF;
        // 1. 初始化COM库(让Windows 加载DLLs). 通常在InitInstance()中调用
        // CoInitialize ( NULL )或其它启动代码。MFC 程序使用AfxOleInit()。
        CoInitialize ( NULL );
        // 2. 使用外壳提供的Shell Link组件对象类创建COM对象。.
        // 第四个参数通知COM 需要什么接口(这里是IShellLink)。
        hr = CoCreateInstance ( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pISL );
        if ( SUCCEEDED(hr) ) {
            // 3. 设置快捷方式目标(墙纸文件)的路径。
            hr = pISL->SetPath ( sWallpaper );
            if ( SUCCEEDED(hr) ) {
                // 4. 获取这个对象的第二个接口(IPersistFile)。
                hr = pISL->QueryInterface (IID_IPersistFile, (void **) &pIPF );
                if ( SUCCEEDED(hr) ) {
                    // 5. 调用Save() 方法保存某个文件得快捷方式。第一个参数是
                    // Unicode 串。
                    hr = pIPF->Save (L"C:\\wallpaper.lnk", FALSE );
                    // 6a. 释放IPersistFile 接口。
                    pIPF->Release();
                }
            }
            // 6. 释放IShellLink 接口。
            pISL->Release();
        }
        // 输出错误信息部分这里省略。
        // 7. 收回COM 库。MFC 程序不用这一步,它自动完成。
        CoUninitialize();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    [面试直通]操作系统核心之存储系统(上)
    java计算机毕业设计springboot+vue园区管理系统
    【JavaWeb的从0到1构建知识体系(三)】JDBC和Lombok的使用
    Axios源码仿写与二次封装
    当OpenHarmony遇上OpenEuler
    [python 刷题] 287 Find the Duplicate Number
    SATA系列专题之三:3.2 Transport Layer传输层FIS Retry机制解析
    SolrCloud环境搭建
    CJSON解析json字符串示例
    基于中文金融知识的 LLaMA 系微调模型的智能问答系统:LLaMA大模型训练微调推理等详细教学
  • 原文地址:https://blog.csdn.net/weixin_44248637/article/details/126547931