CGdiObjMgr:

Maintains a GDI objects. You can define your object in the form of:
CGdiObjMgr<[Handle]> obj;
the [Handle] could be one of HBITMAP / HPEN / HBRUSH / HFONT (without brackets).

CDCMgrs:

Maintains a DC handle. As the replacement of the direct calls' to DC APIs. Used to define your object like this:
CDCMgrs<[old gdi object types' lists]> oYourDc;

CSelectGoToDc:

The replacement of the direct calls' to SelectObject. Used to define your object like this:
CSelectGoToDc<[The gdi object types that will be proceeded], [old gdi object types' lists*]> oseler(odc);
* The lists must be exactly the same to those for declaring the odc.

Usages/Sample:

Assumes that there is code here you would have written:
{
    PAINTSTRUCT ps;
    HPEN hpn = ::CreatePen(PS_SOLID, 1, 0xff00ff);
    HDC hdc = ::BeginPaint(hwnd, &ps);

    if(hpn != NULL) // N1.
    {
        HPEN hpnOld = (HPEN)::SelectObject(hdc, hpn); // N3.

        if(hpnOld != NULL) // N2.
        {
            ::MoveToEx(hdc, 0, 0, NULL);
            ::LineTo(hdc, 400, 300, NULL);
            ::SelectObject(hdc, hpnOld); // N7.
        }
        else
            return;// ** N5.
    }
    ::EndPaint(hwnd, &ps); // N6.
    ::DeleteObject(hpn); // N4.
}

I would say that the Line N1, N2 would be discarded by many coders. The Line N4, N6 and N7 is always forgotten like in Line N5, which causes the resource leaking. Still, It's possible that someone may wrong place the Line N7 after N6.
When the painting code is large, the coders couldn't provide everything right in a short while. I used the MFC and found that it can't fix user's wrong use of SelectObject calls in some special cases.

Now we can write the code like this:
{
    ::nsAssistantEnhX::nsAutoGdiProcessor::CPaintClientDCMgr<a> odc(hwnd);
    ::nsAssistantEnhX::nsAutoGdiProcessor::CGdiObjMgr<HPEN> opn;
    ::nsAssistantEnhX::nsAutoGdiProcessor::CSelectGoToDc<HPEN, a> opnsel(odc);

    opn = ::CreatePen(PS_SOLID, 1, 0xff00ff);
    if(opn != NULL) // N1.
    {
        if(opnsel.ReSelectGoToDc(opn)) // N2.
        {
            ::MoveToEx(odc, 0, 0, NULL);
            ::LineTo(odc, 400, 300, NULL);
        }
        else
            return;// N5.
    }
}
The 'a's shall be replaced by 'HPEN's there. If there are more than one GDI object types were used, all the 'a's in that code must be identical.
{
    ::nsAssistantEnhX::nsAutoGdiProcessor::CPaintClientDCMgr<HPEN,HBRUSH> odc(hwnd);
    ::nsAssistantEnhX::nsAutoGdiProcessor::CGdiObjMgr<HPEN> opn;
    ::nsAssistantEnhX::nsAutoGdiProcessor::CGdiObjMgr<HBRUSH> obsh;
    ::nsAssistantEnhX::nsAutoGdiProcessor::CSelectGoToDc<HPEN, HPEN,HBRUSH> opnsel(odc);
    ::nsAssistantEnhX::nsAutoGdiProcessor::CSelectGoToDc<HBRUSH, HPEN,HBRUSH> obshsel(odc);

    obsh = ::CreateSolidBrush(0x00ffff);
    if(obsh != NULL)
    {
        if(obshsel.ReSelectGoToDc(obsh))
        {
            ::Rectangle(odc, 0, 0, 400, 400);
        }
        //else
            //return;
    }
    opn = ::CreatePen(PS_SOLID, 1, 0xff00ff);
    if(opn != NULL)
    {
        if(opnsel.ReSelectGoToDc(opn))
        {
            ::MoveToEx(odc, 0, 0, NULL);
            ::LineTo(odc, 400, 300, NULL);
        }
        //else
            //return;
    }
}
Wait a second: Maybe you would ask why the DC classes in the library take GDI objects' bodies? Is that rigorous in concept? Just remember that a DC object takes several(default) GDI objects itself, you can swap them out by passing other valid GDI objects you created to the SelectObject and then you have to return all the default objects back before the DC object being unlocked.

general cases

Last edited Mar 22, 2011 at 4:00 PM by UnitUniverse, version 11

Comments

No comments yet.