我试图了解如何使用Windows API,Direct2D和Visual C ++从文件加载和呈现图像。我或多或少都试图在这个主题上关注an MSDN article。我是C ++(在C中经验丰富)和Windows API的新手。
我写了3个函数。
HRESULT imagefactorysetup(IWICImagingFactory * pImageFactory)
{
HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID *) &pImageFactory);
return hr;
}
HRESULT imageload(LPCWSTR filename, IWICImagingFactory * pImageFactory, IWICBitmapFrameDecode * pFrame)
{
IWICBitmapDecoder * pDecoder = NULL;
HRESULT hr = pImageFactory->CreateDecoderFromFilename(filename, NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder);
if (SUCCEEDED(hr))
hr = pDecoder->GetFrame(0, &pFrame);
//Format convert the frame to 32bppPBGRA
IWICFormatConverter * pFormatConverter = NULL;
if (SUCCEEDED(hr))
{
SafeRelease(&pFormatConverter);
hr = pImageFactory->CreateFormatConverter(&pFormatConverter);
}
if (SUCCEEDED(hr))
hr = pFormatConverter->Initialize(pFrame, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom);
return hr;
}
HRESULT imagerender(HWND hWnd, IWICBitmapFrameDecode * pFrame, int x, int y)
{
//Create a D2D render target properties
D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties = D2D1::RenderTargetProperties();
//Set the DPI to be the default system DPI to allow direct mapping
//between image pixels and desktop pixels in different system DPI settings
renderTargetProperties.dpiX = DEFAULT_DPI;
renderTargetProperties.dpiY = DEFAULT_DPI;
//Create a D2D render target
D2D1_SIZE_U sz = D2D1::SizeU(MAINWINDOWWIDTH, MAINWINDOWHEIGHT); //Change size
ID2D1Factory * pD2DFactory;
HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory1), NULL, (LPVOID *) &pD2DFactory);
ID2D1RenderTarget * pRenderTarget;
//renderTargetProperties, D2D1::HwndRenderTargetProperties(hWnd, sz), &pRenderTarget);
hr = pD2DFactory->CreateHwndRenderTarget(&renderTargetProperties, D2D1::HwndRenderTargetProperties(hWnd, sz), &pRenderTarget);
ID2D1Bitmap * pD2DBitmap = NULL;
pRenderTarget->CreateBitmapFromWicBitmap(pFrame, NULL, &pD2DBitmap);
D2D1_SIZE_F size = pD2DBitmap->GetSize();
D2D1_POINT_2F origin = D2D1::Point2F((float) x, (float) y);
if (pD2DBitmap)
pRenderTarget->DrawBitmap(pD2DBitmap, D2D1::RectF(origin.x, origin.y, origin.x + size.width, origin.y + size.height));
return hr;
}
问题:
1)以下行给出了一个错误。我尝试在MSDN上阅读一些文档但不确定是什么问题。
hr = pD2DFactory->CreateHwndRenderTarget(&renderTargetProperties, D2D1::HwndRenderTargetProperties(hWnd, sz), &pRenderTarget);
错误:
IntelliSense: no instance of overloaded function "ID2D1Factory::CreateHwndRenderTarget" matches the argument list
argument types are: (D2D1_RENDER_TARGET_PROPERTIES *, D2D1_HWND_RENDER_TARGET_PROPERTIES, ID2D1RenderTarget **)
object type is: ID2D1Factory 68 18
2)一般来说,是否存在一种更为惯用/有效的方法来解决将文件从文件渲染到窗口的问题而不是我尝试过的问题?我以前的编程经验严格来自C。
答案 0 :(得分:7)
没问题。您可以使用GDI +加载Windows本机支持的任何图像。 然后,您可以使用GDI绘制它。
这是将(透明)PNG绘制到对话框背景的简短示例。我用MinGW32和Code :: Blocks构建了它。您需要链接msimg32
和gdiplus
库以使用AlphaBlend和Bitmap类(以及初始化/关闭GDI +的函数)。
可能值得一提的要点是:
Bitmap
类。<强> Main.cpp的强>
#define WINVER 0x0500 // for AlphaBlend
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <gdiplus.h>
#include "resource.h"
using namespace Gdiplus;
HINSTANCE hInst;
void setClientSize(HWND mHwnd, int width, int height)
{
RECT wndRect, clientRect, mRect;
int clientX, clientY, windowX, windowY, difX, difY;
GetWindowRect(mHwnd, &wndRect);
GetClientRect(mHwnd, &clientRect);
clientX = clientRect.right - clientRect.left;
clientY = clientRect.bottom - clientRect.top;
windowX = wndRect.right - wndRect.left;
windowY = wndRect.bottom - wndRect.top;
difX = windowX - clientX;
difY = windowY - clientY;
// GetWindowRect(mHwnd, &mRect);
POINT topLeft = {wndRect.left, wndRect.top};
// ScreenToClient(mParentHwnd, &topLeft);
SetWindowPos(mHwnd, HWND_TOP, topLeft.x, topLeft.y, width+difX, height+difY, SWP_NOZORDER);
}
HBITMAP mLoadImg(wchar_t *filename)
{
Bitmap mBitmap(filename,false);
HBITMAP result;
mBitmap.GetHBITMAP(0x00000000, &result);
return result;
}
void onPaint(HWND hwnd, HBITMAP bkg)
{
HDC memDC, hdc;
PAINTSTRUCT ps;
HBITMAP old;
RECT clientRect;
int width, height;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &clientRect);
width = clientRect.right - clientRect.left;
height = clientRect.bottom - clientRect.top;
memDC = CreateCompatibleDC(NULL);
old = (HBITMAP)SelectObject(memDC, bkg);
byte alpha = 255;
BLENDFUNCTION bf = {AC_SRC_OVER,0,alpha,AC_SRC_ALPHA};
AlphaBlend(hdc, 0,0,width,height, memDC, 0,0, width,height, bf);
// try the below instead of AlphaBlend - they each rely on the fact I've resized the
// client area to the same size as the image I'll draw on it.
// BitBlt(hdc, 0,0, clientRect.right,clientRect.bottom, memDC, 0,0, SRCCOPY);
SelectObject(memDC, old);
DeleteDC(memDC);
EndPaint(hwnd, &ps);
}
BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HBITMAP mBkg;
switch(uMsg)
{
case WM_INITDIALOG:
{
mBkg = mLoadImg(L"wiki.png");
BITMAP bm;
GetObject(mBkg, sizeof(bm), &bm);
setClientSize(hwndDlg, bm.bmWidth, bm.bmHeight);
}
return TRUE;
case WM_ERASEBKGND:
{
RECT clientRect;
HBRUSH bkgBrush = CreateSolidBrush( RGB(255,0,0) );
GetClientRect(hwndDlg, &clientRect);
FillRect( (HDC)wParam, &clientRect, bkgBrush);
DeleteObject(bkgBrush);
}
return 1;
case WM_PAINT:
onPaint(hwndDlg, mBkg);
return 0;
case WM_CLOSE:
{
EndDialog(hwndDlg, 0);
}
return TRUE;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
}
}
return TRUE;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
hInst=hInstance;
InitCommonControls();
int retVal = DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
GdiplusShutdown(gdiplusToken);
return retVal;
}
<强> RESOURCE.H 强>
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define DLG_MAIN 100
<强> RESOURCE.RC 强>
// Generated by ResEdit 1.6.2
// Copyright (C) 2006-2014
// http://www.resedit.net
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
//
// Dialog resources
//
DLG_MAIN DIALOG 0, 0, 186, 95
STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_THICKFRAME | WS_SYSMENU
EXSTYLE WS_EX_WINDOWEDGE
CAPTION "Dialog"
FONT 8, "Ms Shell Dlg"
{
}
<强> Wiki.png 强>
<强>结果强>