bitmap.c

来自「一个类似windows」· C语言 代码 · 共 622 行 · 第 1/2 页

C
622
字号
      ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL);
      /*
       * FIXME:
       * Remove this after proper support for alpha icons will be finished.
       */
      if (ColorBits > 8)
         ColorBits = 8;
   }

   /* Pick the best size. */
   dirEntry = CURSORICON_FindBestCursorFile( IconDIR, width, height, ColorBits );
   if (!dirEntry)
   {
      DeleteDC(hScreenDc);
      UnmapViewOfFile(IconDIR);
      return NULL;
   }

   if ( dirEntry->dwDIBOffset > filesize )
   {
      DeleteDC(hScreenDc);
      UnmapViewOfFile(IconDIR);
      return NULL;
   }

   if ( dirEntry->dwDIBOffset + dirEntry->dwDIBSize > filesize ){
      DeleteDC(hScreenDc);
      UnmapViewOfFile(IconDIR);
      return NULL;
   }

   SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwDIBSize);
   if (SafeIconImage == NULL)
   {
      DeleteDC(hScreenDc);
      UnmapViewOfFile(IconDIR);
      return NULL;
   }

   memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwDIBOffset, dirEntry->dwDIBSize);
   UnmapViewOfFile(IconDIR);

   /* At this point we have a copy of the icon image to play with. */

   SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;

   if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
   {
      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
      ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
      HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
   }
   else
   {
      ColorCount = SafeIconImage->icHeader.biClrUsed;
      if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
         ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
      HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
   }

   /* Make data point to the start of the XOR image data. */
   Data = (PBYTE)SafeIconImage + HeaderSize;

   hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);
   RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
   DeleteDC(hScreenDc);

   return hIcon;
}


static HANDLE
LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
{
   HANDLE hResource;
   HANDLE hFile;
   HANDLE hSection;
   LPBITMAPINFO BitmapInfo;
   LPBITMAPINFO PrivateInfo;
   HDC hScreenDc;
   HANDLE hBitmap;
   ULONG HeaderSize;
   ULONG ColorCount;
   PVOID Data;

   if (!(fuLoad & LR_LOADFROMFILE))
   {
      if (hInstance == NULL)
         hInstance = User32Instance;

      hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
      if (hResource == NULL)
         return NULL;
      hResource = LoadResource(hInstance, hResource);
      if (hResource == NULL)
         return NULL;
      BitmapInfo = LockResource(hResource);
      if (BitmapInfo == NULL)
         return NULL;
   }
   else
   {
      hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
                          OPEN_EXISTING, 0, NULL);
      if (hFile == INVALID_HANDLE_VALUE)
         return NULL;

      hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
      CloseHandle(hFile);
      if (hSection == NULL)
         return NULL;

      BitmapInfo = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
      CloseHandle(hSection);
      if (BitmapInfo == NULL)
         return NULL;

      BitmapInfo = (LPBITMAPINFO)((ULONG_PTR)BitmapInfo + sizeof(BITMAPFILEHEADER));
   }

   if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
   {
      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;
      ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
      HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
   }
   else
   {
      ColorCount = BitmapInfo->bmiHeader.biClrUsed;
      if (ColorCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
         ColorCount = 1 << BitmapInfo->bmiHeader.biBitCount;
      HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
   }
   Data = (PVOID)((ULONG_PTR)BitmapInfo + HeaderSize);

   PrivateInfo = RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize);
   if (PrivateInfo == NULL)
   {
      if (fuLoad & LR_LOADFROMFILE)
         UnmapViewOfFile(BitmapInfo);
      return NULL;
   }
   memcpy(PrivateInfo, BitmapInfo, HeaderSize);

   /* FIXME: Handle color conversion and transparency. */

   hScreenDc = CreateCompatibleDC(NULL);
   if (hScreenDc == NULL)
   {
      RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
      if (fuLoad & LR_LOADFROMFILE)
         UnmapViewOfFile(BitmapInfo);
      return NULL;
   }

   if (fuLoad & LR_CREATEDIBSECTION)
   {
      DIBSECTION Dib;

      hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL,
                                 0, 0);
      GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);
      SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,
                DIB_RGB_COLORS);
   }
   else
   {
      hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT,
                               Data, PrivateInfo, DIB_RGB_COLORS);
   }

   RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
   DeleteDC(hScreenDc);
   if (fuLoad & LR_LOADFROMFILE)
      UnmapViewOfFile(BitmapInfo);

   return hBitmap;
}

HANDLE STDCALL
LoadImageW(
   IN HINSTANCE hinst,
   IN LPCWSTR lpszName,
   IN UINT uType,
   IN INT cxDesired,
   IN INT cyDesired,
   IN UINT fuLoad)
{
   if (fuLoad & LR_DEFAULTSIZE)
   {
      if (uType == IMAGE_ICON)
      {
         if (cxDesired == 0)
            cxDesired = GetSystemMetrics(SM_CXICON);
         if (cyDesired == 0)
            cyDesired = GetSystemMetrics(SM_CYICON);
      }
      else if (uType == IMAGE_CURSOR)
      {
         if (cxDesired == 0)
            cxDesired = GetSystemMetrics(SM_CXCURSOR);
         if (cyDesired == 0)
            cyDesired = GetSystemMetrics(SM_CYCURSOR);
      }
   }

   switch (uType)
   {
      case IMAGE_BITMAP:
         return LoadBitmapImage(hinst, lpszName, fuLoad);
      case IMAGE_CURSOR:
      case IMAGE_ICON:
         return LoadCursorIconImage(hinst, lpszName, cxDesired, cyDesired,
                                    fuLoad, uType);
      default:
         break;
   }

   return NULL;
}


/*
 * @implemented
 */
HBITMAP STDCALL
LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)
{
   return LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0);
}


/*
 * @implemented
 */
HBITMAP STDCALL
LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
{
   return LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0);
}


/*
 * @unimplemented
 */
HANDLE WINAPI
CopyImage(
   IN HANDLE hnd,
   IN UINT type,
   IN INT desiredx,
   IN INT desiredy,
   IN UINT flags)
{
   HBITMAP res;
   BITMAP bm;

   switch (type)
   {
      case IMAGE_BITMAP:
         {
            DPRINT("WARNING:  Incomplete implementation of CopyImage!\n");
            /*
             * FIXME: Support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
             * LR_COPYRETURNORG, LR_CREATEDIBSECTION and LR_MONOCHROME.
             */
            if (!GetObjectW(hnd, sizeof(bm), &bm))
                return NULL;
            bm.bmBits = NULL;
            if ((res = CreateBitmapIndirect(&bm)))
            {
               char *buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight);
               if (buf == NULL)
               {
                  DeleteObject(res);
                  return NULL;
               }
               GetBitmapBits(hnd, bm.bmWidthBytes * bm.bmHeight, buf);
               SetBitmapBits(res, bm.bmWidthBytes * bm.bmHeight, buf);
               HeapFree(GetProcessHeap(), 0, buf);
            }
            return res;
         }

      case IMAGE_ICON:
         {
            static BOOL IconMsgDisplayed = FALSE;
            /* FIXME: support loading the image as shared from an instance */
            if (!IconMsgDisplayed)
            {
               DPRINT("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
               IconMsgDisplayed = TRUE;
            }
            return CopyIcon(hnd);
         }

      case IMAGE_CURSOR:
         {
            static BOOL IconMsgDisplayed = FALSE;
            /* FIXME: support loading the image as shared from an instance */
            if (!IconMsgDisplayed)
            {
               DPRINT("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
               IconMsgDisplayed = TRUE;
            }
            return CopyCursor(hnd);
         }
   }

   return NULL;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?