Pergunta

I have a 23x23 bitmap which I'm loading from a file into an instance of the IPictureDisp COM interface. I'm loading the picture using OleLoadPicture, passing IID_IPictureDisp. Please assume that this is working and returning me a valid pointer to an IPictureDisp, from which I am able to get an IDispatch pointer without any problem.

I am also able to use IDispatch::Invoke to get the values of the Height and Width members of the picture, which come back as 23 and 23, as expected.

The problem is for some reason using IDispatch::Invoke to invoke the Render method paints a 23x23 monochrome square instead of the picture I expect. Moreover, the colour of the monochrome square corresponds to the colour of the bottom left pixel of the bitmap (which I assume is the zero-eth pixel of the bitmap).

The bitmap I'm trying to render, at 23x23 and blown up to 92x92

What actually paints to the DC. Note that it is a 23x23 image corresponding to the colour of the bottom left pixel of the desired picture

The upper image is the bitmap I'm using (at normal size, and blown up to 4x its size so you can see the colours). The lower image is what is actually rendered.

I think that the problem likely has to do with how I'm calling IDispatch::Invoke.

What I want to do is (pseudocode):

pic.Render(hdc, x, y, w, h, 0, h-1, w, -h, &rc)

where rc is a RECT structure that looks like: left => x ; top => y ; right => x + w ; bottom => y + h.

The C code that eventually gets called is equivalent to this:

// NOTE: x = 0, y = 0, w = 23, h = 23, and -h => 0xffffffe9 in a 32-bit int
DISPPARAMS args = { NULL, NULL, 0, 0 };
args.cArgs = 10;
args.rgvarg = (VARIANT *)alloca(10 * sizeof(VARIANT));
int values[10] = { (int)hdc, x, y, w, h, 0, h-1, w, -h, (int)&rc };
for (int k = 0; k < 10; ++k)
{
    V_VT(args.rgvarg[10-k-1]) = VT_I4;
    V_I4(args.rgvarg[10-k-1]) = values[k];
}

VARIANT result;
VariantInit(&result);

// assume dispid is the correct DISPID for the "Render" method
HRESULT hresult = idisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &args, &result, NULL, NULL);

The value of hresult is 0 (S_OK) when the call returns, but picture rendered is the monochrome image I've shown, using only the colour from the bottom left-hand corner of the image.

How am I misusing IDispatch::Invoke?

Foi útil?

Solução

Alright, so I remember it now. The parameters for Render are confusing. The source values are in himetric values, and not in pixels.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms693441%28v=vs.85%29.aspx

Essentially, it's only using a few pixels as the source, instead of the whole image.

My suggestion is you get the himetric width/height using get_Width and get_Height. Or use AtlPixelToHiMetric to convert them:

http://msdn.microsoft.com/en-CA/library/8ca5swet%28v=vs.90%29.aspx

Outras dicas

I really think we can't assume that you're loading the image correctly. Examine that, and see. I've had issues like this where I assumed it was the rendering code, when it in fact was the image loading code. Ensure that your source data is of perfect quality, and find a way to examine the data once it's loaded. I think you may be surprised as to what you find.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top