GVKun编程网logo

Linux下的“句柄”(文件句柄,窗口句柄)(linux文件句柄是什么)

16

此处将为大家介绍关于Linux下的“句柄”的详细内容,并且为您解答有关文件句柄,窗口句柄的相关问题,此外,我们还将为您介绍关于c–移动语义和窗口句柄.DeleteObject安全句柄?、c++屏幕截图

此处将为大家介绍关于Linux下的“句柄”的详细内容,并且为您解答有关文件句柄,窗口句柄的相关问题,此外,我们还将为您介绍关于c – 移动语义和窗口句柄. DeleteObject安全句柄?、c++ 屏幕截图指定窗口句柄后台截图返回位图句柄、c++得到窗口句柄、delphi 关于窗口句柄,进程等操作的有用信息。

本文目录一览:

Linux下的“句柄”(文件句柄,窗口句柄)(linux文件句柄是什么)

Linux下的“句柄”(文件句柄,窗口句柄)(linux文件句柄是什么)

在windows中,句柄是一个32位的整数,是内存中维护的一个对象的地址列表的整数索引,这些对象包括:窗口(window)、块(module)、任务(task)、实例 (instance)、文件(file)、内存块(block of memory)、菜单(menu)、控制(control)、字体(font)、资源(resource),包括图标(icon),光标 (cursor),字符串(string)等、GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域(region),以及设备描述表(device context)。

在Linux中,每一个进程都由task_struct 数据结构来定义,即PCB,进程通过PCB中的文件描述符表找到文件描述符fd所指向的文件指针filp,文件描述符表是一个指针数组,每一个元素都指向一个内核的打开文件对象,而fd,就是这个表的下标。当用户打开一个文件时,内核会在内部生成一个打开文件对象,并在这个表里找到一个空项,让这一项指向生成的打开文件对象,并返回这一项的下标作为fd,Linux中的文件描述符类似于Windows下文件句柄的概念,但区别是Windows的文件句柄是一个全局的概念,而Linux下文件句柄的作用域只在本进程空间,其中0(标准输入)、1(标准输出)、2(标准错误)是每一个进程中相同的文件描述符,由操作系统规定好,文件描述符所指向元素的文件指针为struct file结构体,在系统中是一个全局的指针。

在linux的X Window桌面环境下,Window 类似于Windows下的窗口句柄,X11/X.h中定义如下:

typedef unsigned long int XID;
typedef XID Window;
typedef XID Font;
typedef XID Pixmap;
typedef XID Drawable;
typedef XID Cursor;
typedef XID Colormap;
typedef XID GContext;
typedef XID KeySym;

 同时,X的官方解释(参考https://www.x.org/wiki/guide/concepts/#index10h4)如下:

XIDs

Many resources managed by the server are assigned a 32-bit identification number, called an XID, from a server-wide namespace. Each client is assigned a range of identifiers when it first connects to the X server, and whenever it sends a request to create a new Window, Pixmap, Cursor or other XID-labeled resource, the client (usually transparently in Xlib or xcb libraries) picks an unused XID from it''s range and includes it in the request to the server to identify the object created by this request. This allows further requests operating on the new resource to be sent to the server without having to wait for it to process the creation request and return an identifier assignment. Since the namespace is global to the Xserver, clients can reference XID''s from other clients in some contexts, such as moving a window belonging to another client.

大概意思是:

X Server通过一个32比特的标识号标识资源。每一个客户端在第一次连接到X Server时,会被赋值一个标识范围,无论是向X Server请求创建一个Window、Pixmap、或者其他XID标记的资源,客户端(通常对于Xlib或xcb库来说是透明的)从此范围选择一个未使用的XID,同时在向X Server发送请求时包含此XID以识别此次请求创建的资源。这种方式允许同时向X Server请求多个新的资源,而不需要等待每次资源创建成功并返回XID。因为对于X Server来说,域名是全局的,所以在同一个上下文中,不同的客户端之间可以相互引用XID,例如在一个客户端中移动属于另一个客户端的窗口。

在Xorg中,客户端资源使用一个数组保存(dix/resource.c):

static ClientResourceRec clientTable[MAXCLIENTS];

xorg是server/client架构,一个xorg server 最多可以有MAXCLIENTS个client,clientTable中的数据项为ClientResourceRec类型,数组中的每一个元素指向client的资源,定义如下:

typedef struct _ClientResource {
    ResourcePtr *resources;
    int elements; int buckets; int hashsize; /* log(2)(buckets) */ XID fakeID; XID endFakeID; } ClientResourceRec;

 

 其中ResourcePtr *resources为一个数组,存放某个客户端的资源,定义如下:

typedef struct _Resource {
    struct _Resource *next;
    XID id;
    RESTYPE type;
    void *value; } ResourceRec, *ResourcePtr;      

用户进入Linux桌面环境后,使用xwininfo可以获取每个窗口的Window id,即XID,XID中的第0~20位为每个客户端的资源ID,第21~28位为客户端编号,请看如下代码:

Bool
InitClientResources(ClientPtr client)
{
    int i, j;

    if (client == serverClient) {
        lastResourceType = RT_LASTPREDEF;
        lastResourceClass = RC_LASTPREDEF;
        TypeMask = RC_LASTPREDEF - 1;
        free(resourceTypes);
        resourceTypes = malloc(sizeof(predefTypes));
        if (!resourceTypes)
            return FALSE;
        memcpy(resourceTypes, predefTypes, sizeof(predefTypes));
    }
    clientTable[i = client->index].resources =
        malloc(INITBUCKETS * sizeof(ResourcePtr));    
    if (!clientTable[i].resources)
        return FALSE;
    clientTable[i].buckets = INITBUCKETS;
    clientTable[i].elements = 0;
    clientTable[i].hashsize = INITHASHSIZE;
    /* Many IDs allocated from the server client are visible to clients,
     * so we don''t use the SERVER_BIT for them, but we have to start
     * past the magic value constants used in the protocol.  For normal
     * clients, we can start from zero, with SERVER_BIT set.
     */
    clientTable[i].fakeID = client->clientAsMask |
        (client->index ? SERVER_BIT : SERVER_MINID);
    clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;
    for (j = 0; j < INITBUCKETS; j++) {
        clientTable[i].resources[j] = NULL;
    }
    return TRUE;
}

int
HashResourceID(XID id, int numBits)
{
    id &= RESOURCE_ID_MASK;
    switch (numBits)
    {
        case 6:
            return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
        case 7:
            return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
        case 8:
            return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
        case 9:
            return ((int)(0x1FF & (id ^ (id>>9))));
        case 10:
            return ((int)(0x3FF & (id ^ (id>>10))));
        case 11:
            return ((int)(0x7FF & (id ^ (id>>11))));
    }
    if (numBits >= 11)
        return ((int)(0x7FF & (id ^ (id>>11))));
    else
    {
        assert(numBits >= 0);
        return id & ~((~0) << numBits);
    }
}

static XID
AvailableID(int client, XID id, XID maxid, XID goodid)
{
    ResourcePtr res;

    if ((goodid >= id) && (goodid <= maxid))
        return goodid;
    for (; id <= maxid; id++) {
        res = clientTable[client].resources[HashResourceID(id, clientTable[client].hashsize)];
        while (res && (res->id != id))
            res = res->next;
        if (!res)
            return id;
    }
    return 0;
}

 

 从以上代码分析,Xorg通过XID的第21~28位作为索引(假设索引号为client)定位clientTable中的客户端结构体,此结构体中的resources也是一个数组,每个元素指向一个ResourcePtr,此数组大小为INITBUCKETS,相当于创建了INITBUCKETS个资源池,通过0~20位获取资源号后,通过hash算法(xorg中一般使用((int)(0x03F & (id ^ (id>>6) ^ (id>>12))))),将新建的Resource资源放入某个资源池,在一个池子中的Resource以链表方式连接到一起。此种方式应该是在XID查询和资源释放效率间获得一定的平衡。

c – 移动语义和窗口句柄. DeleteObject安全句柄?

c – 移动语义和窗口句柄. DeleteObject安全句柄?

Windows中是否存在某种NULL句柄?如果我通过CreateCompatibleBitmap()创建一个bmp并通过DeleteObject()删除它并想要使用移动语义,我想确保不破坏位图.因此,我必须将HBITMAP设置为可安全删除的值.比如删除nullptr.

解决方法

首先是坏消息.由于历史原因,Windows API中通常没有有效的“无效句柄”值. Windows中的不同子系统将NULL或INVALID_HANDLE_VALUE视为无效句柄值(用于返回无效句柄值和获取句柄值). Related article on Old New Thing.

然而,好消息是,尽管您仍然需要为意外的返回值做好准备(除非您仔细阅读您使用的每个函数的文档),但提供无效值仍然总是在实践中“起作用”.
您可能没有使用正确的指定“无效”值,但它仍然无效,因此该函数将失败.您的应用程序不会崩溃,除了浪费几个cpu周期之外没有任何负面影响.

因此,继续使用NULL(或nullptr),你很好.如果不出意外,对于稍后阅读您的代码的人来说,这是直观的.在您的具体示例中,它也是正确的,因为GDI函数假定NULL为无效.

您几乎可以依赖NULL和INVALID_HANDLE_VALUE都是无效值.虽然我不知道一个要求(如文档中明确说明的那样)有效的HANDLE必须是非零的,但实际上它们总是如此.我愿意打赌你永远不会找到零值的句柄(只是尝试并使用Sysinternals的句柄工具,你的计算机上的任何一个进程都不会有低于20的句柄).

但即使假设NULL可以是一个有效的句柄值,你也必须考虑到在调用main或运行全局构造函数之前已经打开和关闭了一些句柄,你真的没有选择.这意味着假设NULL可能是一个有效的句柄,并且假设它在程序运行时仍然有效,那么这个假设句柄与API函数兼容的类型的机会非常低.

另一方面,有人可能会争辩说应用程序可能打开(无符号)-1个句柄,使INVALID_HANDLE_VALUE成为有效值.

除非你泄漏手柄,否则我无法想象你会如何获得那么多打开手柄.但更重要的是,在达到该数字之前很久,您可能会在64位系统上耗尽内存,并且您将彻底耗尽32位系统上的地址空间.如果INVALID_HANDLE_VALUE是一个有效的句柄永远成为一个问题,你有一个更严重的问题.

c++ 屏幕截图指定窗口句柄后台截图返回位图句柄

c++ 屏幕截图指定窗口句柄后台截图返回位图句柄

/根据窗口句柄后台截图保存成BMP位图文件并且显示到picture 控件上
void GetScreenBmp(HWND hwnd, int left, int top, int width, int height, CHAR* path)
{

    HDC pDC;// 源DC
    //判断是不是窗口句柄如果是的话不能使用GetDC来获取DC 不然截图会是黑屏
    if (hwnd==::GetDesktopWindow())
    {
        pDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
    }
    else
    {
        pDC = ::GetDC(hwnd);//获取屏幕DC(0为全屏,句柄则为窗口)
    }
    int BitPerPixel = ::GetDeviceCaps(pDC, BITSPIXEL);//获得颜色模式
    if (width == 0 && height == 0)//默认宽度和高度为全屏
    {
        width = ::GetDeviceCaps(pDC, HORZRES); //设置图像宽度全屏
        height = ::GetDeviceCaps(pDC, VERTRES); //设置图像高度全屏
    }
    HDC memDC;//内存DC
    memDC = ::CreateCompatibleDC(pDC);
    HBITMAP memBitmap, oldmemBitmap;//建立和屏幕兼容的bitmap
    memBitmap = ::CreateCompatibleBitmap(pDC, width, height);
    oldmemBitmap = (HBITMAP)::SelectObject(memDC, memBitmap);//将memBitmap选入内存DC
    if (hwnd==::GetDesktopWindow())
    {
        BitBlt(memDC,0, 0, width, height, pDC, left, top, SRCCOPY);//图像宽度高度和截取位置
    }
    else
    {
        bool bret = ::PrintWindow(hwnd, memDC, PW_CLIENTONLY);
        if (!bret)
        {
            BitBlt(memDC, 0, 0, width, height, pDC, left, top, SRCCOPY);//图像宽度高度和截取位置
        }
    }
    //以下代码保存memDC中的位图到文件
    BITMAP bmp;
    ::GetObject(memBitmap, sizeof(BITMAP), &bmp);;//获得位图信息
    FILE *fp;
    fopen_s(&fp, path, "w+b");//图片保存路径和方式

    BITMAPINFOHEADER bih = { 0 };//位图信息头
    bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小
    bih.biCompression = BI_RGB;
    bih.biHeight = bmp.bmHeight;//高度
    bih.biPlanes = 1;
    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小
    bih.biWidth = bmp.bmWidth;//宽度

    BITMAPFILEHEADER bfh = { 0 };//位图文件头
    bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量
    bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;//文件总的大小
    bfh.bfType = (WORD)0x4d42;

    fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头
    fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头
    byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据
    GetDIBits(memDC, (HBITMAP)memBitmap, 0, height, p,
        (LPBITMAPINFO)&bih, DIB_RGB_COLORS);//获取位图数据
    fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);//写入位图数据
    delete[] p;
    fclose(fp);
    HWND sBitHwnd = GetDlgItem(g_Hwnd, IDC_STATIC_IMG);
    /*返回内存中的位图句柄 还原原来的内存DC位图句柄 不能直接用 memBitmap我测试好像是不行不知道为什么*/
    HBITMAP oleImage = (HBITMAP)::SelectObject(memDC, oldmemBitmap);
    oleImage = (HBITMAP)SendMessage(sBitHwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)oleImage);
#if 0
    /*这种方法也能把位图显示到picture 控件上*/
    HDC bitDc = NULL;
    bitDc = ::GetDC(sBitHwnd);
    BitBlt(bitDc, 0, 0, bmp.bmWidth, bmp.bmHeight, memDC, 0, 0, SRCCOPY); //内存DC映射到屏幕DC
     ReleaseDC(sBitHwnd, bitDc);
    /*如果需要把位图转换*/
    /*
    CImage image;
    image.Create(nWidth, nHeight, nBitPerPixel);
    BitBlt(image.GetDC(), 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY);
    ::ReleaseDC(NULL, hdcSrc);
    image.ReleaseDC();
    image.Save(path, Gdiplus::ImageFormatPNG);//ImageFormatJPEG
    */
#endif
      DeleteObject(memBitmap);
    DeleteObject(oleImage);
      DeleteDC(memDC);
      ReleaseDC(hwnd,pDC);

}

 

c++得到窗口句柄

c++得到窗口句柄

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string.h>
#include <iostream>

using namespace std;
int main()
{
    HWND hd = GetDesktopWindow();        //得到桌面窗口
    hd = GetWindow(hd, GW_CHILD);        //得到屏幕上第一个子窗口
    char s[200] = { 0 };
    while (hd != NULL)                    //循环得到所有的子窗口
    {
        memset(s, 0, 200);
        GetWindowText(hd, s, 200);
        if (strcmp(s,"计算器")==0)
        {
            cout << s << endl;
            break;
        }

        
        hd = GetNextWindow(hd, GW_HWNDNEXT);
    }

//    PostMessage(hd, WM_KEYDOWN, 0xd, 0x1C0001);
//    PostMessage(hd, WM_KEYUP, 0xd, 0xC01C0001);

    getchar();
    return 0;
}

 

delphi 关于窗口句柄,进程等操作

delphi 关于窗口句柄,进程等操作

总结

以上是小编为你收集整理的delphi 关于窗口句柄,进程等操作全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

我们今天的关于Linux下的“句柄”文件句柄,窗口句柄的分享就到这里,谢谢您的阅读,如果想了解更多关于c – 移动语义和窗口句柄. DeleteObject安全句柄?、c++ 屏幕截图指定窗口句柄后台截图返回位图句柄、c++得到窗口句柄、delphi 关于窗口句柄,进程等操作的相关信息,可以在本站进行搜索。

本文标签: