SDC C-Project CF Review 프로그램
LYW
2021-11-12 039bde2990b5b015232b5da9ff4df0cf1d88ddac
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
// XPTabCtrl.cpp : ±¸Çö ÆÄÀÏÀÔ´Ï´Ù.
//
 
#include "stdafx.h"
#include "XPTabCtrl.h"
 
 
// CXPTabCtrl
 
/***********************************************************************************************************/
// constant string definitions here (or you can put it into resource string table)
#define IDS_UTIL_TAB            _T("TAB")
#define IDS_UTIL_UXTHEME        _T("UxTheme.dll")
#define IDS_UTIL_THEMEACT       _T("IsThemeActive")
#define IDS_UTIL_THEMEOPN       _T("OpenThemeData")
#define IDS_UTIL_THEMEBCKG      _T("DrawThemeBackground")
/***********************************************************************************************************/
 
IMPLEMENT_DYNAMIC(CXPTabCtrl, CTabCtrl)
 
CXPTabCtrl::CXPTabCtrl()
{
    m_bTabExtended=TRUE;            // default is to use extended tab (if it is Themes XP)
    m_eTabOrientation=e_tabBottom;    // default initial orientation is: bottom
    m_ixSelOld=-1;
}
 
CXPTabCtrl::~CXPTabCtrl()
{
}
 
void CXPTabCtrl::InitImageList(UINT nBitmapID)
{
    if(!::IsWindow(GetSafeHwnd()) || m_ilTabs.operator HIMAGELIST())
    { ASSERT(FALSE); return; }                // tab control has to be created first and image list can be created only once
    if(m_ilTabs.Create(nBitmapID, 16, 1, RGB(0xFF,0,0xFF)))    // add an images list with appropriate background (transparent) color
        SetImageList(&m_ilTabs);
}
 
BEGIN_MESSAGE_MAP(CXPTabCtrl, CTabCtrl)
    ON_WM_PAINT()
    ON_NOTIFY_REFLECT(TCN_SELCHANGING,OnTabSelChanging)
    ON_NOTIFY_REFLECT(TCN_SELCHANGE,  OnTabSelChanged)
END_MESSAGE_MAP()
 
 
// CXPTabCtrl ¸Þ½ÃÁö Ã³¸®±âÀÔ´Ï´Ù.
//----------------------------------------------------------------------------------------------------------
void CXPTabCtrl::OnPaint() 
{
    if(!IsExtendedTabTheamedXP())            // if it is not XP or it is not Themes, behave as default
        { Default(); return; }    
    CPaintDC dc(this);                        // device context for painting
 
    CRect rcClip; rcClip.SetRectEmpty();
    dc.GetClipBox(rcClip);
 
    // 1st paint the tab body
    CRect rcPage,rcItem,rcClient;
    GetClientRect(&rcPage);
    rcClient=rcPage;
    AdjustRect(FALSE,rcPage);
    
    switch(m_eTabOrientation)
    {    case e_tabTop:      rcClient.top   =rcPage.top   -2; break;
        case e_tabBottom: rcClient.bottom=rcPage.bottom+3; break;
        case e_tabLeft:      rcClient.left  =rcPage.left  -1; break;
        case e_tabRight:  rcClient.right =rcPage.right +3; break;
        default: ASSERT(FALSE); return;
    }
    UINT uiVertBottm;
    uiVertBottm =(m_eTabOrientation&1)? 8:0;        //  8=bottom
    uiVertBottm|=(m_eTabOrientation&2)?16:0;        // 16=vertical
    UINT uiFlags=1|uiVertBottm;                        //  1=body    
    DrawThemesXpTabItem(&dc, -1, rcClient,uiFlags);    // TABP_PANE=9,0,'TAB'
    
    int nTab=GetItemCount();                        // paint the tabs first and then the borders
    if(!nTab) return;                                // no tab pages added
 
    // 2nd paint the inactive tabs
    CRect ;
    TCHITTESTINFO hti;    hti.flags=0;
    ::GetCursorPos(&hti.pt); ScreenToClient(&hti.pt);
    int ixHot=HitTest(&hti);
    int ixSel=GetCurSel();
        
    for(int ixTab=0; ixTab<nTab; ixTab++)
    {    if(ixTab==ixSel)
            continue;
        VERIFY(GetItemRect(ixTab, &rcItem));
        if(m_eTabOrientation==e_tabLeft) rcItem.right++;
        uiFlags=uiVertBottm|(ixTab==ixHot?4:0);        // 4= hot
        DrawThemesXpTabItem(&dc,ixTab,rcItem,uiFlags);
    }
    // 3rd paint the active selected tab
    VERIFY(GetItemRect(ixSel, &rcItem));            // now selected tab
    rcItem.InflateRect(2,2);
    if(m_eTabOrientation==e_tabTop) rcItem.bottom--;
    uiFlags=uiVertBottm|2;                            // 2= selected
    DrawThemesXpTabItem(&dc, ixSel, rcItem,uiFlags);
}
//----------------------------------------------------------------------------------------------------------
// This function draws Themes Tab control parts: a) Tab-Body and b) Tab-tabs
void CXPTabCtrl::DrawThemesXpTabItem(CDC* pDC, int ixItem, const CRect& rcItem, UINT uiFlag) 
{            // uiFlag(1/0):1=Type(body/tab);2=Sel(y/n);4=Hot(y/n);8=bBottom(y/n);16=rotate(y/n)
    BOOL bBody  =(uiFlag& 1)?TRUE:FALSE;
    BOOL bSel   =(uiFlag& 2)?TRUE:FALSE;
    BOOL bHot   =(uiFlag& 4)?TRUE:FALSE;
    BOOL bBottom=(uiFlag& 8)?TRUE:FALSE;    // mirror
    BOOL bVertic=(uiFlag&16)?TRUE:FALSE;    // rotate
    BOOL bLeftTab=!bBottom && bVertic && !bBody;
 
    CSize szBmp=rcItem.Size();
    if(bVertic) SwapVars(szBmp.cx,szBmp.cy);
    // 1st draw background
    CDC     dcMem;    dcMem .CreateCompatibleDC(pDC);
    CBitmap bmpMem; bmpMem.CreateCompatibleBitmap(pDC,szBmp.cx,szBmp.cy);
    CBitmap* pBmpOld=dcMem.SelectObject(&bmpMem);
    CRect rcMem(CPoint(0,0),szBmp); if(bSel) rcMem.bottom++;
    if(bBody)
         DrawThemesPart(dcMem.GetSafeHdc(), 9, 0, (LPCSTR)IDS_UTIL_TAB, &rcMem);    // TABP_PANE=9,  0, 'TAB'
    else DrawThemesPart(dcMem.GetSafeHdc(), 1, bSel?3:(bHot?2:1), (LPCSTR)IDS_UTIL_TAB, &rcMem);
                                                                // TABP_TABITEM=1, TIS_SELECTED=3:TIS_HOT=2:TIS_NORMAL=1, 'TAB'
    // 2nd init some extra parameters
    BITMAPINFO biOut; ZeroMemory(&biOut,sizeof(BITMAPINFO));    // Fill local pixel arrays
    BITMAPINFOHEADER& bihOut=biOut.bmiHeader;
    bihOut.biSize  =sizeof (BITMAPINFOHEADER);
    bihOut.biCompression=BI_RGB;
    bihOut.biPlanes=1;          bihOut.biBitCount=24;    // force as RGB: 3 bytes,24 bits -> good for rotating bitmap in any resolution
    bihOut.biWidth =szBmp.cx; bihOut.biHeight=szBmp.cy;
 
    int nBmpWdtPS=DWordAlign(szBmp.cx*3);
    int nSzBuffPS=((nBmpWdtPS*szBmp.cy)/8+2)*8;
    LPBYTE pcImg=NULL;
    if(bBottom || bVertic) { pcImg=new BYTE[nSzBuffPS]; ASSERT(pcImg); }
    int nStart=0,nLenSub=0;
    if(bBody && bBottom && !bVertic) nStart=3,nLenSub=4;    // if bottom oriented flip the body contest only (no shadows were flipped)
    // 3rd if it is left oriented tab, draw tab context before mirroring or rotating (before GetDIBits)
    if(bVertic)
    {    if(bBody || !bBottom) bihOut.biHeight=-szBmp.cy;
        if(!bBottom && !bBody && ixItem>=0)                    // 
        {    if(bSel) rcMem.bottom--;
            DrawTabItem(&dcMem, ixItem, rcMem, uiFlag); ixItem=-1;
    }    }                                                        // rotate or mirror
    // 4th get bits (for rotate) and mirror: body=(all except top) tab=(all except top)
    if(bVertic || bBottom)                                        // get bits: 
    {    GetDIBits(*pDC, bmpMem.operator HBITMAP(),nStart,szBmp.cy-nLenSub,pcImg,&biOut,DIB_RGB_COLORS);
        if(bBottom)                                    // mirror: body=(bottom and right) tab=(bottom and right)
        {    bihOut.biHeight=-szBmp.cy;                 // to mirror bitmap is eough to use negative height between Get/SetDIBits
            SetDIBits(*pDC, bmpMem.operator HBITMAP(),nStart,szBmp.cy-nLenSub,pcImg,&biOut,DIB_RGB_COLORS);
            if(bBody && bVertic)                    // when it is right oriented body -> flip twice, first flip border shadows, than flip shaded inside body again
            {    nStart=2; nLenSub=4; bihOut.biHeight=szBmp.cy;
                GetDIBits(*pDC, bmpMem.operator HBITMAP(),nStart,szBmp.cy-nLenSub,pcImg,&biOut,DIB_RGB_COLORS);
                bihOut.biHeight=-szBmp.cy;            // to mirror bitmap is eough to use negative height between Get/SetDIBits
                SetDIBits(*pDC, bmpMem.operator HBITMAP(),nStart,szBmp.cy-nLenSub,pcImg,&biOut,DIB_RGB_COLORS);
    }    }    }
    // 5th if it is bottom or right oriented tab, draw after mirroring background (do GetDIBits again)
    if(!bBody && ixItem>=0)                            // 
    {    if(bSel) rcMem.bottom--;
        DrawTabItem(&dcMem, ixItem, rcMem, uiFlag);
        if(bVertic)                                            // if it is right tab, do GetDIBits again
        {    bihOut.biHeight=-szBmp.cy;
            GetDIBits(*pDC, bmpMem.operator HBITMAP(),nStart,szBmp.cy-nLenSub,pcImg,&biOut,DIB_RGB_COLORS);
    }    }
    // 6th: do rotate now, finaly
    if(bVertic)                            // force rotating bitmap as RGB -> good for any resolution
    {    SwapVars(szBmp.cx,szBmp.cy);
 
        int nBmpWdtPD=DWordAlign(szBmp.cx*3);
        int nPadD=nBmpWdtPD-szBmp.cx*3;
        int nSzBuffPD=((nBmpWdtPD*szBmp.cy)/8+2)*8;
        LPBYTE pcImgRotate=new BYTE[nSzBuffPD]; ASSERT(pcImgRotate);
        int nWidth,nHeight=szBmp.cy,nHeight1=nHeight-1;
        //====================================
        //------------------------------------
                                // here is the example how to speed up lengthy repeatetive processing by using inline assembler
//    #define __USE_MASM__        // the same processing is in C and in asm. To use C -> comment the beginning of this line
                                // Do the actual whole RGB bitmap rotating in C or assembler
    #ifndef __USE_MASM__
        LPBYTE pcImgS=pcImg;
        LPBYTE pcImgD=pcImgRotate;
        int ixHeight=0;
        BOOL bLast=FALSE;
        while(ixHeight<nHeight)                    // for all destination height lines
        {    nWidth=szBmp.cx;
            if(ixHeight==nHeight1) { bLast=TRUE; nWidth--; }
            
            while(nWidth--)
            {    *(PDWORD)pcImgD=*(PDWORD)pcImgS; // do all Rgb triplets read/write qicker as DWORD
                pcImgS+=nBmpWdtPS;    // increment source in padded source lines
                pcImgD+=3;            // increment destination in rgb triplets
            }
            if(bLast)                // when the last line, the last pixel - colud be a problem if bitmap DWORD alligned 
                for(int c=3;c;c--) *pcImgD++=*pcImgS++;        // (only last three bytes available->could not read/write DWORD)!!
            else
            {    ixHeight++;
                pcImgD+=nPadD;                // destination bitmap horizontal padding to DWORD
                pcImgS=pcImg+(ixHeight*3);    // reset the source to the begining of the next vertical line
        }    }
    #else    // __USE_MASM__
            nBmpWdtPS-=4;                    // adjust esi increment (due to esi self-incrementing by movsd)
            nWidth=szBmp.cx;
        __asm
        {        mov        esi, pcImg            // source index
                mov        edi, pcImgRotate    // destination index
                xor        ebx, ebx            // vertical counter
            loop_height:
                mov        ecx, nWidth            // horizontal counter
                cmp        ebx, nHeight1        // check is it the last line
                jne        loop_width
                dec        ecx                    // if it is decremnt for the last pixel
 
            loop_width:
                movsd                        // copies 4 bytes and increments source and destination by 4 (we need only 3 bytes copied 'one pixel' RGB triplet)
                dec        edi                    // adjust edi to 'as incremented by 3'
                add        esi,nBmpWdtPS        // adjust esi to the next source line
                loop    loop_width            // loop one hotizontal destination line 
 
                cmp        ebx, nHeight1        // check is it the last line
                je        do_last                // if not last, do incrementing here
                                            
                inc        ebx                    // increment vertical counter
                add        edi, nPadD            // adjust destination index by possible padding to DWORD
                mov        esi, ebx            // reset the source index: add vertical counter * 3 
                shl        esi, 1                // (is the same as * 2 +1*)
                add        esi, ebx            // +1*
                add        esi, pcImg            // add to the beginning of the source
                jmp        loop_height            // loop whole height
 
            do_last:                        // the last pixel is done by
                movsw                        // moving first two bytes
                movsb                        // and than by moving the very last byte
        }
    #endif //     __USE_MASM__
        dcMem.SelectObject(pBmpOld); bmpMem.DeleteObject();        // recreate rotated bitmap
        bmpMem.CreateCompatibleBitmap(pDC,szBmp.cx,szBmp.cy);
        dcMem.SelectObject(&bmpMem);
        bihOut.biWidth =szBmp.cx; bihOut.biHeight=bBody?-szBmp.cy:szBmp.cy;
        SetDIBits(*pDC, bmpMem.operator HBITMAP(),0,szBmp.cy,pcImgRotate,&biOut,DIB_RGB_COLORS); // set rotated bitmap bits
        delete pcImgRotate;
    }
    if(pcImg) delete pcImg;
    // 6th blit mirrored/rotated image to the screen
    pDC->BitBlt(rcItem.left,rcItem.top,szBmp.cx,szBmp.cy,&dcMem,0,0,SRCCOPY); // 
    dcMem.SelectObject(pBmpOld);
}
//----------------------------------------------------------------------------------------------------------
// draw tab item context: possible icon and text
void CXPTabCtrl::DrawTabItem(CDC* pDC, int ixItem, const CRect& rcItemC, UINT uiFlags)
{
    TC_ITEM tci;   CString sText;
    tci.mask      =TCIF_TEXT | TCIF_IMAGE;
    tci.pszText   =sText.GetBuffer(128);
    tci.cchTextMax=127;
    GetItem(ixItem,&tci);
    sText.ReleaseBuffer();
 
    BOOL bSel   =(uiFlags&2)?TRUE:FALSE;
    BOOL bBottom=(uiFlags&8)?TRUE:FALSE;
    CRect rcItem=rcItemC;
    if(bSel) rcItem.bottom -= 1;
    else     rcItem.bottom += 2;
    rcItem.left+=(bBottom?3:6);                    // text & icon
    rcItem.top +=(bBottom?3:2) + (bSel ? 1 : (bBottom?0:3));
 
    int nOldMode=pDC->SetBkMode(TRANSPARENT);
    HIMAGELIST hilTabs = (HIMAGELIST)TabCtrl_GetImageList(GetSafeHwnd());    // icon
    if(hilTabs && tci.iImage>=0)
    {    ImageList_Draw(hilTabs, tci.iImage, *pDC, rcItem.left+(bSel?2:0), rcItem.top+(bSel?0:-2), ILD_TRANSPARENT);
        rcItem.left+=19;
    }
    else rcItem.OffsetRect(-2,0);
 
    if(sText.GetLength())
    {    CFont* pOldFont=pDC->SelectObject(GetFont());        // prepare dc
        rcItem.right-=3;                        // text
        CRect rect(0,0,rcItem.Width(),20);
        ::DrawText(pDC->GetSafeHdc(),sText.GetBuffer(sText.GetLength()+4),-1,rect,DT_CALCRECT|DT_SINGLELINE|DT_MODIFYSTRING|DT_END_ELLIPSIS);
        sText.ReleaseBuffer();
 
        rcItem.OffsetRect((bBottom?-1:0),(bSel?1:-1));
        pDC->DrawText(sText, rcItem, DT_NOPREFIX|DT_CENTER);
        pDC->SelectObject(pOldFont);
    }
    pDC->SetBkMode(nOldMode);
}
//----------------------------------------------------------------------------------------------------------
BOOL CXPTabCtrl::IsExtendedTabTheamedXP()
{
    if(!m_bTabExtended || !::IsWindow(GetSafeHwnd()))
        return FALSE;
    DWORD dwStyle=GetStyle();
    m_eTabOrientation=(dwStyle&TCS_BOTTOM)?e_tabBottom:e_tabTop;
    if(dwStyle&TCS_VERTICAL)
        m_eTabOrientation=(m_eTabOrientation==e_tabTop)?e_tabLeft:e_tabRight;
#ifdef USE_DEFAULT_XP_TOPTAB
    if(m_eTabOrientation==e_tabTop)    return FALSE;
#endif
    return IsThemeActiveXP()?TRUE:FALSE;
}
//==========================================================================================================
// these two messages are necessary only to properly redraw deselected tab background, because 
void CXPTabCtrl::OnTabSelChanging(NMHDR* pNMHDR, LRESULT* pResult)    // selected rect was inflated by 2 points
{
    UNUSED_ALWAYS(pNMHDR);
    m_ixSelOld=GetCurSel();
    *pResult=0L;
}
//----------------------------------------------------------------------------------------------------------
void CXPTabCtrl::OnTabSelChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
    UNUSED_ALWAYS(pNMHDR);
    if(m_ixSelOld>=0 && m_ixSelOld!=GetCurSel()  && IsExtendedTabTheamedXP())            // else  
    {    CWnd* pWndParent=GetParent();
        if(pWndParent)
        {    CRect rcOldSel; GetItemRect(m_ixSelOld, rcOldSel); rcOldSel.InflateRect(2,2);
            ClientToScreen(&rcOldSel); pWndParent->ScreenToClient(&rcOldSel);
            pWndParent->InvalidateRect(rcOldSel);
    }    }
    *pResult=1L;
}
/***********************************************************************************************************/
// Helper functions
/***********************************************************************************************************/
int DWordAlign(int n)
    { const int rem=n%4; if(rem) n+=(4-rem); return n; }
//----------------------------------------------------------------------------------------------------------
BOOL IsThemeActiveEx()
{                                // check theme activity always (could change during application running)
    USES_CONVERSION;
    
    HINSTANCE hDll=LoadLibrary(CString((LPCTSTR)IDS_UTIL_UXTHEME));                            // 'UxTheme.dll'
    if(hDll==NULL) return FALSE;                // the DLL won't be available on anything except Windows XP
    UINT (PASCAL *pfnIsThemeActive)();
    
#ifdef X
    (FARPROC&)pfnIsThemeActive=GetProcAddress(hDll,W2A(IDS_UTIL_THEMEACT));    // 'IsThemeActive'
#else
    (FARPROC&)pfnIsThemeActive=GetProcAddress(hDll,IDS_UTIL_THEMEACT);    // 'IsThemeActive'
#endif
 
    UINT uiThemeActive=0;
    if(pfnIsThemeActive)
        uiThemeActive=pfnIsThemeActive();            
    FreeLibrary(hDll);
    return uiThemeActive?TRUE:FALSE;
}
//----------------------------------------------------------------------------------------------------------
#define PACKVERSION(major,minor) MAKELONG(minor,major)
DWORD GetWinVersion()
{
    static DWORD c_dwWinVers=0;    // check win version only once (will not change during application)
    if(!c_dwWinVers)
    {    OSVERSIONINFO osvi;    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));    // Initialize the OSVERSIONINFO structure.
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        GetVersionEx(&osvi);
        c_dwWinVers=PACKVERSION(osvi.dwMajorVersion,osvi.dwMinorVersion);
    }
    return c_dwWinVers;
}
//----------------------------------------------------------------------------------------------------------
BOOL IsWinXP()         { return GetWinVersion()>=PACKVERSION(5,1)?TRUE:FALSE; }
//----------------------------------------------------------------------------------------------------------
BOOL IsThemeActiveXP() { return (IsWinXP()  && IsThemeActiveEx())?TRUE:FALSE; }
//----------------------------------------------------------------------------------------------------------
 
#define WPART_NAME_SZ 128
HRESULT DrawThemesPart(HDC hDC, int iPartId, int iStateId, LPCSTR uiPartNameID, LPRECT prcBox)
{
    USES_CONVERSION;
 
    if(!IsWinXP()) return E_FAIL;
    HINSTANCE hDll=LoadLibrary(CString((LPCTSTR)IDS_UTIL_UXTHEME));                                // 'UxTheme.dll'
    if(!hDll) return E_FAIL;
    BOOL (PASCAL* pfnIsThemeActive)();    UINT hTheme=0;
 
#ifdef X
    (FARPROC&)pfnIsThemeActive=GetProcAddress(hDll,W2A(IDS_UTIL_THEMEACT));        // 'IsThemeActive'
#else
    (FARPROC&)pfnIsThemeActive=GetProcAddress(hDll,IDS_UTIL_THEMEACT);        // 'IsThemeActive'
#endif
 
    HRESULT hResult=E_FAIL;
    if(pfnIsThemeActive && pfnIsThemeActive())
    {    CString sPartName(uiPartNameID);
        if(sPartName.GetLength()>0)
        {    WCHAR swPartName[WPART_NAME_SZ];
            
#ifdef X
            MultiByteToWideChar(CP_ACP,0,W2A(sPartName),-1,swPartName,sizeof(swPartName)/sizeof(WCHAR));
#else
            MultiByteToWideChar(CP_ACP,0,sPartName,-1,swPartName,sizeof(swPartName)/sizeof(WCHAR));
#endif
 
            UINT (PASCAL* pfnOpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
            
 
#ifdef X
            (FARPROC&)pfnOpenThemeData=GetProcAddress(hDll,W2A(IDS_UTIL_THEMEOPN));// 'OpenThemeData'
#else
            (FARPROC&)pfnOpenThemeData=GetProcAddress(hDll,IDS_UTIL_THEMEOPN);// 'OpenThemeData'
#endif
 
            if(pfnOpenThemeData && (hTheme=pfnOpenThemeData(NULL, swPartName))!=0)
            {    UINT (PASCAL* pfnDrawThemeBackground)(UINT htheme,HDC hdc,int iPartID,int iStateID,const RECT* prcBx,const RECT* prcClip);
                
 
#ifdef X
                (FARPROC&)pfnDrawThemeBackground=GetProcAddress(hDll,W2A(IDS_UTIL_THEMEBCKG));    // 'DrawThemeBackground'
#else
                (FARPROC&)pfnDrawThemeBackground=GetProcAddress(hDll,IDS_UTIL_THEMEBCKG);    // 'DrawThemeBackground'
#endif
 
                if(pfnDrawThemeBackground)
                    hResult=pfnDrawThemeBackground(hTheme, hDC, iPartId, iStateId, prcBox, NULL);
    }    }    }
    FreeLibrary(hDll);
    return hResult;
}
//----------------------------------------------------------------------------------------------------------