0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Wine の HDC, DC, DCE, HWND の関係

Last updated at Posted at 2018-02-26

Wine の HDC, DC, DCE, HWND の関係

関連リンク

[目次] (https://qiita.com/Yutaka_Aoki/items/9d38ea98406f4096435b)

DC 型 = sturct DC

~/wine/dlls/gdi32/gdi_private.h
typedef struct tagDC {
    HDC          hSelf;            /* Handle to this DC */
    struct gdi_physdev nulldrv;    /* physdev for the null driver */
    PHYSDEV      physDev;          /* current top of the physdev stack */
    DWORD        thread;           /* thread owning the DC */
    LONG         refcount;         /* thread refcount */
    LONG         dirty;            /* dirty flag */
    LONG         disabled;         /* get_dc_ptr() will return NULL.  Controlled by DCHF_(DISABLE|ENABLE)DC */
    INT          saveLevel;
    struct tagDC *saved_dc;
    DWORD_PTR    dwHookData;
    DCHOOKPROC   hookProc;         /* DC hook */
    BOOL         bounds_enabled:1; /* bounds tracking is enabled */
    BOOL         path_open:1;      /* path is currently open (only for saved DCs) */

    POINT        wnd_org;          /* Window origin */
    SIZE         wnd_ext;          /* Window extent */
    POINT        vport_org;        /* Viewport origin */
    SIZE         vport_ext;        /* Viewport extent */
    SIZE         virtual_res;      /* Initially HORZRES,VERTRES. Changed by SetVirtualResolution */
    SIZE         virtual_size;     /* Initially HORZSIZE,VERTSIZE. Changed by SetVirtualResolution */
    RECT         vis_rect;         /* visible rectangle in screen coords */
    RECT         device_rect;      /* rectangle for the whole device */
    int          pixel_format;     /* pixel format (for memory DCs) */
    UINT         aa_flags;         /* anti-aliasing flags to pass to GetGlyphOutline for current font */
    FLOAT        miterLimit;

    int           flags;
    DWORD         layout;
    HRGN          hClipRgn;      /* Clip region */
    HRGN          hMetaRgn;      /* Meta region */
    HRGN          hVisRgn;       /* Visible region */
    HRGN          region;        /* Total DC region (intersection of clip and visible) */
    HPEN          hPen;
    HBRUSH        hBrush;
    HFONT         hFont;
    HBITMAP       hBitmap;
    HPALETTE      hPalette;

    struct gdi_path *path;

    UINT          font_code_page;
    WORD          ROPmode;
    WORD          polyFillMode;
    WORD          stretchBltMode;
    WORD          relAbsMode;
    WORD          backgroundMode;
    COLORREF      backgroundColor;
    COLORREF      textColor;
    COLORREF      dcBrushColor;
    COLORREF      dcPenColor;
    POINT         brush_org;

    DWORD         mapperFlags;       /* Font mapper flags */
    WORD          textAlign;         /* Text alignment from SetTextAlign() */
    INT           charExtra;         /* Spacing from SetTextCharacterExtra() */
    INT           breakExtra;        /* breakTotalExtra / breakCount */
    INT           breakRem;          /* breakTotalExtra % breakCount */
    INT           MapMode;
    INT           GraphicsMode;      /* Graphics mode */
    ABORTPROC     pAbortProc;        /* AbortProc for Printing */
    POINT         cur_pos;           /* Current position */
    INT           ArcDirection;
    XFORM         xformWorld2Wnd;    /* World-to-window transformation */
    XFORM         xformWorld2Vport;  /* World-to-viewport transformation */
    XFORM         xformVport2World;  /* Inverse of the above transformation */
    BOOL          vport2WorldValid;  /* Is xformVport2World valid? */
    RECT          bounds;            /* Current bounding rect */
} DC;

struct dce

~/wine/dlls/user32/painting.c
struct dce {
    struct list entry;         /* entry in global DCE list */
    HDC         hdc;
    HWND        hwnd;
    HRGN        clip_rgn;
    DWORD       flags;
    LONG        count;         /* usage count; 0 or 1 for cache DCEs, always 1 for window DCEs,
                                  always >= 1 for class DCEs */
};

DC と struct dce の相互リンク

結論的には:

HDC			hdc;
struct dce	*dce;
DC			*dc		= get_dc_ptr( hdc );

dce->hdc       = hdc;
dc->dwHookData = dce:

根拠 :

~/dlls/user32/painting.c
// Allocate a new DCE.
static struct dce *alloc_dce(void)
{
    struct dce *dce;

    if (!(dce = HeapAlloc( GetProcessHeap(), 0, sizeof(*dce) ))) return NULL;
    if (!(dce->hdc = CreateDCW( displayW, NULL, NULL, NULL )))
    {
        HeapFree( GetProcessHeap(), 0, dce );
        return 0;
    }
    dce->hwnd      = 0;
    dce->clip_rgn  = 0;
    dce->flags     = 0;
    dce->count     = 1;

    /* store DCE handle in DC hook data field */
    SetDCHook( dce->hdc, dc_hook, (DWORD_PTR)dce );
    SetHookFlags( dce->hdc, DCHF_INVALIDATEVISRGN );
    return dce;
}
~/wine/dlls/gdi32/dc.c
// Note: this doesn't exist in Win32, we add it here because user32 needs it.
BOOL WINAPI SetDCHook( HDC hdc, DCHOOKPROC hookProc, DWORD_PTR dwHookData )
{
    DC *dc = get_dc_ptr( hdc );

    if (!dc) return FALSE;

    dc->dwHookData = dwHookData;
    dc->hookProc = hookProc;
    release_dc_ptr( dc );
    return TRUE;
}

// Note: this doesn't exist in Win32, we add it here because user32 needs it.
DWORD_PTR WINAPI GetDCHook( HDC hdc, DCHOOKPROC *proc )
{
    DC *dc = get_dc_ptr( hdc );
    DWORD_PTR ret;

    if (!dc) return 0;
    if (proc) *proc = dc->hookProc;
    ret = dc->dwHookData;
    release_dc_ptr( dc );
    return ret;
}

hdc から dc を取得

DC *dc = get_dc_ptr( hdc );

/* dc に関する処理 */

release_dc_ptr( dc );

get_dc_ptr() を呼び出すと、「GDI lock」なる処理が行われる。「unlock」するために、release_dc_ptr() が必要らしい。

dc から dce を取得

(絶対に正しく動作するかは不明です)

独自関数
struct dce *get_dce_of_dc( DC *dc )
{
	return	(struct dce *)(dc->dwHookData);
}

dce から hdc を取得

独自関数
HDC get_hdc_of_dce( struct dce *dce )
{
	return	dce->hdc;
}

dc から hdc を取得

(絶対に正しく動作するかは不明です)

独自関数1
HDC get_hdc_of_dce( DC *dc )
{
	return	dc->hSelf;
}
独自関数2
HDC get_hdc_of_dce2( DC *dc )
{
	struct dce	*dce	= (struct dce *)(dc->dwHookData);
	
	return	dce->hdc;
}

HDC から HWND を取得する方法

実際に上手く行くかは条件次第なので、注意が必要であり、実際に使うには、条件を満たしているかをチェックする必要がある。正確な条件は今のところよく分かってない。そもそも、CompatibleDC で HBITMAP を使う場合などは、HDC には、HWND が対応していない場合があるはず。危険なので、このままコピペして使うのは絶対してはならない。

独自関数
HWND __get_hwnd_of_hdc( HDC hdc )
{
	DC			*dc		= get_dc_ptr( hdc );
	
	struct dce	*dce	= (struct dce *)(dc->dwHookData);
	HWNE		hwnd	= dce->hwnd;
    
    release_dc_ptr( dc );
    
    return	hwnd;
}

DC *get_dc_ptr( HDC hdc)

~/wine/dlls/gdi32/dc.c
// Retrieve a DC pointer but release the GDI lock.
DC *get_dc_ptr( HDC hdc )
{
    DC *dc = get_dc_obj( hdc );
    if (!dc) return NULL;
    if (dc->disabled)
    {
        GDI_ReleaseObj( hdc );
        return NULL;
    }

    if (!InterlockedCompareExchange( &dc->refcount, 1, 0 ))
    {
        dc->thread = GetCurrentThreadId();
    }
    else if (dc->thread != GetCurrentThreadId())
    {
        WARN( "dc %p belongs to thread %04x\n", hdc, dc->thread );
        GDI_ReleaseObj( hdc );
        return NULL;
    }
    else InterlockedIncrement( &dc->refcount );

    GDI_ReleaseObj( hdc );
    return dc;
}

static inline DC *get_dc_obj( HDC hdc )
{
    WORD type;
    DC *dc = get_any_obj_ptr( hdc, &type );
    if (!dc) return NULL;

    switch (type)
    {
    case OBJ_DC:
    case OBJ_MEMDC:
    case OBJ_METADC:
    case OBJ_ENHMETADC:
        return dc;
    default:
        GDI_ReleaseObj( hdc );
        SetLastError( ERROR_INVALID_HANDLE );
        return NULL;
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?