Windows2000/private/shell/comctl32/mirror.c
2020-09-30 17:12:32 +02:00

168 lines
4.1 KiB
C

/****************************** Module*Header *****************************\
* Module Name: mirror.c *
* This module contains all the Right-To-Left (RTL) Mirroring support *
* routines used to Right-To-Left mirror an icon on the fly so that *
* it would be displayed normal on a RTL mirrored localized OS. This is *
* mainly a concern for 3rd party Apps. *
* Created: 01-Feb-1998 8:41:18 pm *
* Author: Samer Arafeh [samera] *
* Copyright (c) 1998 Microsoft Corporation *
*/
#include "ctlspriv.h"
/*
* MirrorIcon
* Mirror an Icon , given an Icon handle so that when these icons are displayed
* on a Mirrored DC, they end would be displayed normal.
* History:
* 04-Feb-1998 samera Created
*/
BOOL WINAPI MirrorIcon(HICON* phiconSmall, HICON* phiconLarge)
{
HDC hdcScreen;
HBITMAP hbm, hbmMask, hbmOld,hbmOldMask;
BITMAP bm;
HICON hicon[2] = {NULL,NULL};
HICON hiconNew[2] = {NULL,NULL};
ICONINFO ii ;
int i;
#ifdef WINNT
#define IPIXELOFFSET 0
#else // !WINNT
#define IPIXELOFFSET 2
#endif WINNT
// Synchronize access to global DCs now!
// Allocate DCs if we didn't so far.
ENTERCRITICAL;
if (!g_hdc && !g_hdcMask)
{
g_hdc = CreateCompatibleDC(NULL);
if (g_hdc)
{
#ifndef UNIX
#ifndef WINNT
SetObjectOwner(g_hdc, HINST_THISDLL);
#endif
#endif /* !UNIX */
g_hdcMask = CreateCompatibleDC(NULL);
if( g_hdcMask )
{
#ifndef UNIX
#ifndef WINNT
SetObjectOwner(g_hdcMask, HINST_THISDLL);
#endif
#endif /* !UNIX */
SET_DC_RTL_MIRRORED(g_hdc);
SET_DC_RTL_MIRRORED(g_hdcMask);
}
else
{
DeleteDC( g_hdc );
g_hdc = NULL;
}
}
}
if (phiconSmall)
hicon[0] = *phiconSmall;
if (phiconLarge)
hicon[1] = *phiconLarge;
// Acquire the screen DC
hdcScreen = GetDC(NULL);
if (g_hdc && g_hdcMask && hdcScreen)
{
for( i=0 ; i<(sizeof(hicon)/sizeof(HICON)) ; i++ )
{
if( hicon[i] )
{
if( GetIconInfo(hicon[i], &ii) &&
GetObject(ii.hbmColor, sizeof(BITMAP), &bm))
{
// I don't want these.
DeleteObject( ii.hbmMask );
DeleteObject( ii.hbmColor );
ii.hbmMask = ii.hbmColor = NULL;
hbm = CreateCompatibleBitmap(hdcScreen, bm.bmWidth, bm.bmHeight);
hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
hbmOld = (HBITMAP)SelectObject(g_hdc, hbm);
hbmOldMask = (HBITMAP)SelectObject(g_hdcMask, hbmMask);
DrawIconEx(g_hdc, IPIXELOFFSET, 0, hicon[i], bm.bmWidth, bm.bmHeight, 0,
NULL, DI_IMAGE);
DrawIconEx(g_hdcMask, IPIXELOFFSET, 0, hicon[i], bm.bmWidth, bm.bmHeight, 0,
NULL, DI_MASK);
SelectObject(g_hdc, hbmOld);
SelectObject(g_hdcMask, hbmOldMask);
// create the new mirrored icon, and delete bmps
ii.hbmMask = hbmMask;
ii.hbmColor = hbm;
hiconNew[i] = CreateIconIndirect(&ii);
DeleteObject(hbm);
DeleteObject(hbmMask);
}
}
}
}
ReleaseDC(NULL, hdcScreen);
// Now we can reuse the global DCs
LEAVECRITICAL;
// Update icons if needed, and destroy old ones!
if (hicon[0] && hiconNew[0])
{
*phiconSmall = hiconNew[0];
DestroyIcon(hicon[0]);
}
if (hicon[1] && hiconNew[1])
{
*phiconLarge = hiconNew[1];
// Don't delete twice
if (hicon[1] != hicon[0])
DestroyIcon(hicon[1]);
}
return TRUE;
}