Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: UpdateLayeredWindow fails with no error reported



Permlink Replies: 25 - Last Post: May 21, 2015 1:52 PM Last Post By: Remy Lebeau (Te... Threads: [ Previous | Next ]
Boba ½°

Posts: 73
Registered: 12/19/03
UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 12, 2015 10:48 PM
BlankDear Reader; my Outlook can't find old discussions
on the GDI+ subject, so I am probably repeating...
In my simple GDI+ test project, something is wrong,
but I do not see what is missing. Please help.
My Form1 has 2 buttons and Unit1.h has these lines added:
private: // User declarations
  Gdiplus::GdiplusStartupInput gdiplusStartupInput;
  ULONG_PTR gdiplusToken;
  HWND hWndTst;
  HBITMAP hbmp, hbmp0;
  HDC hdcMem, hdcScr;
public:  // User declarations
  __fastcall TForm1(TComponent* Owner);
  __fastcall ~TForm1();
{/code}
so the Form1's c/d-tors have some GDI+ code:

__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){
if( Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) !=
Gdiplus::Ok ) ShowMessage("GdiplusStartup");
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1(){
if(gdiplusToken) Gdiplus::GdiplusShutdown(gdiplusToken);
}
//---------------------------------------------------------------------------
{/code}
and the TButton::OnClick event handlers look as following:
{code}
void __fastcall TForm1::Button1Click(TObject*){
WNDCLASSEX wndcls;
DWORD dwErr;
::ZeroMemory(&wndcls, sizeof(wndcls));
wndcls.cbSize = sizeof(wndcls);
wndcls.lpfnWndProc = DefWindowProc;
wndcls.hInstance = HInstance;
wndcls.hbrBackground = (HBRUSH)::GetStockObject(DC_BRUSH);
wndcls.lpszClassName = "wndclstst";
if( !::RegisterClassEx(&wndcls) ) return;
hWndTst = ::CreateWindowEx(WS_EX_LAYERED, "wndclstst", NULL,
WS_VISIBLE|WS_POPUP, 100, 100, 200, 200,
NULL, NULL, HInstance, NULL);
if(!hWndTst){ ShowMessage("CreateWindowEx"); return; }
hdcScr = ::GetDC(NULL);
hdcMem = ::CreateCompatibleDC(hdcScr);
hbmp = ::CreateCompatibleBitmap(hdcMem, 100, 100);
if(!hbmp){ ShowMessage("CreateCompatibleBitmap"); return; }
hbmp0 = (HBITMAP)::SelectObject(hdcMem, hbmp);
RECT rect={0, 0, 100, 100};
::FillRect(hdcMem, &rect, (HBRUSH)(COLOR_3DFACE+1));
POINT pntSrc={0, 0}, pntWndPos={100, 100};
SIZE pntWndSize = {200, 200};
BLENDFUNCTION bf = {AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA};
if( !::UpdateLayeredWindow(hWndTst, NULL/*hdcScr*/, &pntWndPos,
&pntWndSize,
hdcMem, &pntSrc, RGB(0,0,0), &bf, ULW_ALPHA) ){
dwErr = ::GetLastError();
ShowMessage( "UpdateLayeredWindow
"+IntToStr((int)dwErr) );//dwErr==NO_ERROR
//why do I get the above message?
}
}//Button1Click
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject*){
if(hbmp0) ::SelectObject(hdcMem, hbmp0);
if(hbmp) ::DeleteObject(hbmp);
if(hdcMem) ::DeleteDC(hdcMem);
if(hWndTst) ::DestroyWindow(hWndTst);
::UnregisterClass("wndclstst", HInstance);
if(hdcScr) ::ReleaseDC(NULL, hdcScr);
}//Button2Click
//---------------------------------------------------------------------------
{/code}
many thanks in advance!
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 13, 2015 12:31 AM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

In my simple GDI+ test project, something is wrong,
but I do not see what is missing. Please help.

Using the exact code you have provided, UpdateLayeredWindow() does not return
FALSE for me unless I drop my display color depth below 32bit (since you
are trying to use 32bit per-pixel alpha blending), but then GetLastError()
reports 317 and not 0. UpdateLayeredWindow() has been known to sometimes
fail with GetLastError=0 in 16/24-bit modes, though.

In 32bit display mode, UpdateLayeredWindow() returns TRUE for me, but I do
not see the window appear onscreen. Which makes sense, because your bitmap
is not providing any alpha value, so the window is hidden from view. But
I know it is being "shown" because the app's Form is losing focus when pressing
Button1.

I do notice your in-memory bitmap is smaller than the window, though. Is
that intentional? The window is 200x200, but the bitmap is 100x100.

Since you are trying to do 32bit alpha blending, you should be using a 32bit
bitmap, like the BLENDFUNCTION documentation says to:

When the AlphaFormat member is AC_SRC_ALPHA, the source bitmap must be 32
bpp. If it is not, the AlphaBlend function will fail.

Try creating a 32bit DIB via CreateDibSection() instead of a screen-resolution
DDB via CreateCompatibleBitmap().

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 13, 2015 8:28 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" <no dot spam at no dot spam dot com> wrote in message
news:723858 at forums dot embarcadero dot com...
Using the exact code you have provided, UpdateLayeredWindow() does not
return
FALSE for me unless I drop my display color depth below 32bit (since you
are trying to use 32bit per-pixel alpha blending), but then GetLastError()
reports 317 and not 0. UpdateLayeredWindow() has been known to sometimes
fail with GetLastError=0 in 16/24-bit modes, though.

it is 32 bits per pixel.

In 32bit display mode, UpdateLayeredWindow() returns TRUE for me, but I do
not see the window appear onscreen. Which makes sense, because your
bitmap
is not providing any alpha value, so the window is hidden from view. But
I know it is being "shown" because the app's Form is losing focus when
pressing
Button1.

yes, the window does get created, but it "looks invisible".

I do notice your in-memory bitmap is smaller than the window, though. Is
that intentional? The window is 200x200, but the bitmap is 100x100.

no intention; just wanted to be sure it is smaller than the window itself.

Since you are trying to do 32bit alpha blending, you should be using a
32bit
bitmap, like the BLENDFUNCTION documentation says to:

i thought CreateCompatibleBitmap generates a 32-bit map just like
the current video setting is... but my 1st arg is wrong - see below.

When the AlphaFormat member is AC_SRC_ALPHA, the source bitmap must be 32
bpp. If it is not, the AlphaBlend function will fail.
Try creating a 32bit DIB via CreateDibSection() instead of a
screen-resolution
DDB via CreateCompatibleBitmap().

THIS did the trick! Many thanks for the solution, Remy!
ashamed, I should've noticed the typo in my code before posting:
hbmp = ::CreateCompatibleBitmap(hdcMem, 100, 100); - memory compatible
hbmp = ::CreateCompatibleBitmap(hdcScr, 100, 100); - SCREEN compatible.
been so nervous lately watching football/soccer, but i got the finalists
right! and now i hate seeing Chiellini playing against Suarez ;(
thanks again!
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 14, 2015 9:29 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" wrote in message
news:723858 at forums dot embarcadero dot com...
I do notice your in-memory bitmap is smaller than the window, though.
Is that intentional? The window is 200x200, but the bitmap is 100x100.

for the call to succeed, supplied surface area can not be smaller than
the window, but I was just testing.

Remy, I have a couple of unrelated questions: what is error code 317?
Does your version of GDI+ allow bitORing for the last parameter to
UpdateLayeredWindow call (dwFlags); I don't understand why the help
insists on "This parameter can be one of the following values." TIA
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 14, 2015 11:29 AM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

what is error code 317?

Officially, it is documented as ERROR_MR_MID_NOT_FOUND, which is a FormatMessage()
error code. But noone knows why UpdateLayeredWindow() reports it, or what
it means. It is not documented, but it has been observed.

Does your version of GDI+ allow bitORing for the last parameter to
UpdateLayeredWindow call (dwFlags);

GDI+ and UpdateLayeredWindow() are not related to each other in any way.

I don't understand why the help insists on "This parameter can be
one of the following values."

Because it really does only support 1 flag at a time.

A layered window cannot be alphablended/transparent and opaque at the same
time, so you cannot combine those flags.

UpdateLayeredWindow() does not support applying both alphablending and transparency
at the same time.

SetLayeredWindowAttributes() supports applying both at one time, but it does
not support per-pixel alpha blending, like UpdateLayeredWindow() does.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 14, 2015 2:32 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" wrote in message
news:724024 at forums dot embarcadero dot com...
... GDI+ and UpdateLayeredWindow() are not related to each other in any
way.

if my 82385 still serves me, they came out around same time. thanks for your
time.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 14, 2015 2:46 PM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

if my 82385 still serves me, they came out around same time.

If they did, that is pure coincidence. They are still not related to each
other in any way.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 9:08 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" wrote in message
news:724024 at forums dot embarcadero dot com...
... A layered window cannot be alphablended/transparent and
opaque at the same time, so you cannot combine those flags.
UpdateLayeredWindow() does not support applying both alphablending
and transparency at the same time.

ok. so I call UpdateLayeredWindow 2 times and the second call
undoes/overwrites the effect of the 1st one. Is there a way
to make those calls and achieve both effects?
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 9:34 AM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

ok. so I call UpdateLayeredWindow 2 times and the second call
undoes/overwrites the effect of the 1st one. Is there a way to
make those calls and achieve both effects?

Not with UpdateLayeredWindow(), no. As I told you earlier, you would have
to use SetLayeredWindowAttributes() instead, as it supports setting both
alphablend and transparency at the same time. Unless you are trying to use
per-pixel alpha blending, in which case you have to use UpdateLayeredWindow(),
as SetLayeredWindowAttributes() applies to the entire window as a whole.
If you want both alpha blending and transparency, you are going to have
to use per-pixel alpha blending, and simply set the alpha to 0 for any pixels
that you want to be transparent.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 11:40 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" wrote in message
news:724243 at forums dot embarcadero dot com...
... you would have to use SetLayeredWindowAttributes() instead,
as it supports setting both alphablend and transparency at the
same time.

calling SetLayeredWindowAttributes(,RGB(0xff,0,0),0x80,LWA_ALPHA)
does show semitransparent window, and SetLayeredWindowAttributes(,
RGB(0xff,0,0),0x80,LWA_COLORKEY) removes all red pixels showing
holes instead; but calling SetLayeredWindowAttributes(,RGB(0xff,0,0),
0x80,LWA_ALPHA|LWA_COLORKEY) gives the same result as just LWA_ALPHA:
red pixels are half-tone blended. This tells me I need to pre-process
the original bitmap somehow:
  Gdiplus::Bitmap bmp("test.bmp");
  Gdiplus::Graphics grfx(hdcMem);
  grfx.DrawImage(bmp,0,0);
{/code}
and I use BitBlt in the WM_PAINT handler:

hdc=BeginPaint(,);
BitBlt(hdc,0,0,,,hdcMem,0,0,SRCCPY);
EndPaint(,);
{/code}
btw, I create my test.bmp with mspaint and save it as 24-bit map.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 11:51 AM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

calling SetLayeredWindowAttributes(,RGB(0xff,0,0),0x80,LWA_ALPHA)
does show semitransparent window, and SetLayeredWindowAttributes(,
RGB(0xff,0,0),0x80,LWA_COLORKEY) removes all red pixels showing
holes instead; but calling SetLayeredWindowAttributes(,RGB(0xff,0,0),
0x80,LWA_ALPHA|LWA_COLORKEY) gives the same result as just LWA_ALPHA:
red pixels are half-tone blended.

Works fine for me. Red pixels are completely transparent, and the rest of
the window is translucent.

This tells me I need to pre-process the original bitmap somehow:

Not with SetLayeredWindowAttributes(), no. With UpdateLayeredWindow(), yes.

Gdiplus::Bitmap bmp("test.bmp");
Gdiplus::Graphics grfx(hdcMem);
grfx.DrawImage(bmp,0,0);
{/code}
and I use BitBlt in the WM_PAINT handler:

hdc=BeginPaint(,);
BitBlt(hdc,0,0,,,hdcMem,0,0,SRCCPY);
EndPaint(,);
{/code}

How are you creating hdcMem? Please show a complete example.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 1:17 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" wrote in message
news:724260 at forums dot embarcadero dot com...

Works fine for me. Red pixels are completely transparent, and the rest of
the window is translucent.

hmmm... I run this test on XP (it has BCB12 aka 2009 installed).

How are you creating hdcMem? Please show a complete example.

it is shown in my post of 05/13:
<code>
hdcScr = ::GetDC(NULL);
hdcMem = ::CreateCompatibleDC(hdcScr);
</code>
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 1:32 PM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

it is shown in my post of 05/13:
<code>
hdcScr = ::GetDC(NULL);
hdcMem = ::CreateCompatibleDC(hdcScr);
</code>

Again, I would have appreciated a COMPLETE example like I asked for, instead
of having to hunt for information. But whatever.

So, if I am reading this right, you are creating a HDC for the screen, drawing
your bitmap onto it, and then BitBlt()'ing that onto the HDC that BeginPaint()
provides, is that correct? Can you reproduce the problem without using
a bitmap at all? Just draw some colors directly on the painting HDC and
see what happens. That is what I did in my test - I used the TForm::OnPaint
event to draw a red square on the form's Canvas (which has the HDC from WM_PAINT),
and then set the form's AlphaBlendValue and TransparentColorValue properties
(as they use SetLayeredWindowAttributes() internally). The effect worked
as expected (transparency and translucency working together), which proves
that SetLayeredWindowAttributes() itself works fine, so there is something
wrong in your setup. Can you please show a COMPLETE code example demonstrating
what you are trying to accomplish?

- -
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 2:24 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" <no dot spam at no dot spam dot com> wrote in message
news:724272 at forums dot embarcadero dot com...
... you are creating a HDC for the screen, drawing
your bitmap onto it, and then BitBlt()'ing that onto
the HDC that BeginPaint() > provides, is that correct?

it is.

Can you reproduce the problem without using a bitmap at all?

no.

Just draw some colors directly on the painting HDC and
see what happens.

everything works as expected.

which proves that SetLayeredWindowAttributes() itself works fine,
so there is something wrong in your setup. Can you please show
a COMPLETE code example demonstrating what you are trying to
accomplish?

I'm on it, "but I need a little time..."
Boba ½°

Posts: 73
Registered: 12/19/03
SetLayeredWindowAttributes fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 19, 2015 10:51 PM   in response to: Boba ½° in response to: Boba ½°
Jim wrote in "Yes, the River Knows":
"I'm going, but I need a little time..."

{code}
#include <gdiplus.h>
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
HWND hWndTst;
HBITMAP hbmp, hbmp0;
HDC hdcScr;
public: // User declarations
HDC hdcMem;
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
//===========================================================================
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
if( Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) !=
Gdiplus::Ok ){ ShowMessage("GdiplusStartup"); }
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
Gdiplus::GdiplusShutdown( gdiplusToken );
}
//---------------------------------------------------------------------------
LRESULT CALLBACK
WndProcTst(HWND hWnd, UINT uMsg, WPARAM wPrm, LPARAM lPrm){
HDC hdc;
PAINTSTRUCT ps;
switch( uMsg ){
case WM_CREATE:
case WM_DESTROY: return 0;
case WM_PAINT:
hdc = ::BeginPaint(hWnd, &ps);
if( hdc ){
::BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
Form1->hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
/*::InflateRect(&ps.rcPaint, -40, -40);
::FillRect(hdc, &ps.rcPaint, ::CreateSolidBrush( RGB(0xff,0,0) ));
caution: brush handles may leak*/
}
::EndPaint(hWnd, &ps);
return 0;
}//switch( uMsg ){
return ::DefWindowProc(hWnd, uMsg, wPrm, lPrm);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
WNDCLASSEX wndcls;
::ZeroMemory( &wndcls, sizeof(wndcls) );
wndcls.cbSize = sizeof(wndcls);
//wndcls.lpfnWndProc = DefWindowProc;
wndcls.lpfnWndProc = WndProcTst; //need to process WM_PAINT
wndcls.hInstance = HInstance;
wndcls.lpszClassName = "wndclstst";
if( !::RegisterClassEx(&wndcls) ){ ShowMessage("RegisterClass"); return; }
hWndTst = ::CreateWindowEx(WS_EX_NOACTIVATE|WS_EX_LAYERED,
"wndclstst", NULL,
WS_VISIBLE|WS_POPUP, 100, 100, 200, 200,
NULL, NULL, HInstance, NULL );
if( !hWndTst ){ ShowMessage( "CreateWindowEx" ); return; }
hdcScr = ::GetDC(NULL);
hdcMem = ::CreateCompatibleDC(hdcScr);
hbmp = ::CreateCompatibleBitmap(hdcScr, 200, 200);
if( !hbmp ){ ShowMessage( "CreateCompatibleBitmap" ); return; }
hbmp0 = (HBITMAP)::SelectObject( hdcMem, hbmp );
Gdiplus::Bitmap bmp("tst.bmp"); //24-bit map
Gdiplus::Graphics grfx(/*Canvas->Handle*/hdcMem);//uncomment to see bmp
if(grfx.DrawImage(&bmp, 0, 0) != Gdiplus::Ok){
ShowMessage( "DrawImage" ); return;
}
if( !::SetLayeredWindowAttributes(hWndTst, RGB(0xff,0,0), 0x80,
LWA_COLORKEY|LWA_ALPHA) ){
ShowMessage( "SetLayout "+IntToStr((int)::GetLastError()) ); return;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
::SelectObject( hdcMem, hbmp0 );
if(hbmp) ::DeleteObject(hbmp);
if(hdcMem) ::DeleteDC(hdcMem);
if(hWndTst) ::DestroyWindow(hWndTst);
::UnregisterClass("wndclstst", HInstance);
if(hdcScr) ::ReleaseDC(NULL, hdcScr);
}
//---------------------------------------------------------------------------
{/code}
thanks for looking at the above.
Unrelated: does mspaint allow to save 32-bit maps?
Boba ½°

Posts: 73
Registered: 12/19/03
Re: SetLayeredWindowAttributes fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 20, 2015 9:24 AM   in response to: Boba ½° in response to: Boba ½°
Gdiplus::Bitmap bmp("tst.bmp"); //24-bit map
the bitmap is 200x200
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SetLayeredWindowAttributes fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 20, 2015 10:56 AM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

<snip code>

Oh, this code again.

After making some tweaks to make the code actually compile and function correctly
(Gdiplus::Bitmap does not accept a char* as input, and BitBlt() needs to
specify 0x0 for the source bitmap coordinates), this code works fine for
me with SetLayeredWindowAttributes(). The window is transparent as expected.
So double-check your BMP file, make sure it really is using PURE red (255,0,0)
pixels. When I created a red bitmap with mspaint, the resulting pixels were
not PURE red (237,28,36), which explains why the transparency was not working
correctly. When I then used a different graphics editor to "fix" the bitmap
pixels, the transparency worked correctly without changing the code.

That being said, I would suggest drawing the Bitmap directly on the HDC provided
by BeginPaint() in WM_PAINT, don't even bother creating an in-memory HDC
at all (and certainly not one that is "compatible" with the screen instead
of the actual window):

//---------------------------------------------------------------------------
 
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <gdiplus.h>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
    TButton *Button1;
    TButton *Button2;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);
private:	// User declarations
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    HWND hWndTst;
public:		// User declarations
    Gdiplus::Bitmap *bmp;
    __fastcall TForm56(TComponent* Owner);
    __fastcall ~TForm56();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm56 *Form51;
//---------------------------------------------------------------------------
#endif


//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm56::TForm56(TComponent* Owner)
    : TForm(Owner)
{
    if( Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) 
!= Gdiplus::Ok )
    {
        ShowMessage("GdiplusStartup");
        return;
    }
    bmp = Gdiplus::Bitmap::FromFile(L"tst.bmp");
    if (!bmp)
    {
        ShowMessage("Bitmap::FromFile");
        return;
    }
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
    delete bmp;
    Gdiplus::GdiplusShutdown( gdiplusToken );
}
//---------------------------------------------------------------------------
LRESULT CALLBACK WndProcTst(HWND hWnd, UINT uMsg, WPARAM wPrm, LPARAM lPrm)
{
    if (uMsg == WM_PAINT)
    {
        PAINTSTRUCT ps;
        HDC hdc = ::BeginPaint(hWnd, &ps);
        if( hdc && Form56->bmp )
        {
            Gdiplus::Graphics grfx(hdc);
            grfx.DrawImage(Form56->bmp, (int) ps.rcPaint.left, (int) ps.rcPaint.top);
        }
        ::EndPaint(hWnd, &ps);
        return 0;
    }
    return ::DefWindowProc(hWnd, uMsg, wPrm, lPrm);
}
//---------------------------------------------------------------------------
void __fastcall TForm56::Button1Click(TObject *Sender)
{
    WNDCLASSEX wndcls;
    ::ZeroMemory( &wndcls, sizeof(wndcls) );
    wndcls.cbSize = sizeof(wndcls);
    //wndcls.lpfnWndProc = DefWindowProc;
    wndcls.lpfnWndProc = WndProcTst; //need to process WM_PAINT
    wndcls.hInstance = HInstance;
    wndcls.lpszClassName = TEXT("wndclstst");
    if( !::RegisterClassEx(&wndcls) )
    {
        ShowMessage("RegisterClass");
        return;
    }
    hWndTst = ::CreateWindowEx(WS_EX_NOACTIVATE|WS_EX_LAYERED, TEXT("wndclstst"), 
NULL, WS_VISIBLE|WS_POPUP, 100, 100, 200, 200, NULL, NULL, HInstance, NULL );
    if( !hWndTst )
    {
        ShowMessage( "CreateWindowEx" );
        return;
    }
    if( !::SetLayeredWindowAttributes(hWndTst, RGB(0xff,0,0), 0x80, LWA_COLORKEY|LWA_ALPHA) 
)
    {
        ShowMessage( "SetLayout "+IntToStr((int)::GetLastError()) );
        return;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm56::Button2Click(TObject *Sender)
{
    if (hWndTst)
    {
        ::DestroyWindow(hWndTst);
        hWndTst = NULL;
    }
    ::UnregisterClass("wndclstst", HInstance);
}
//---------------------------------------------------------------------------


::FillRect(hdc, &ps.rcPaint, ::CreateSolidBrush( RGB(0xff,0,0) ));
caution: brush handles may leak*/

The reason for the leak is because you are not releasing the brush after
you are finished using it:

HBRUSH hBrush = ::CreateSolidBrush( RGB(0xff,0,0) );
::FillRect(hdc, &ps.rcPaint, hBrush);
::DeleteObject(hBrush);


does mspaint allow to save 32-bit maps?

No.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 20, 2015 2:18 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" wrote in message
news:724388 at forums dot embarcadero dot com...
... BitBlt() needs to specify 0x0 for the source bitmap coordinates

not sure what you mean.

So double-check your BMP file, make sure it really is using PURE
red (255,0,0) pixels. When I created a red bitmap with mspaint,
the resulting pixels were not PURE red (237,28,36),

right on it!

I would suggest drawing the Bitmap directly on the HDC provided
by BeginPaint() in WM_PAINT, don't even bother creating an
in-memory HDC at all (and certainly not one that is "compatible"
with the screen instead of the actual window)

the need for this in-memory bitmap is dictated by project design:
it's dynamically (and slowly) created image only part of which is
occasionally being shown on that layered window.
Will report on the bitmap pure redness soonest.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 20, 2015 2:34 PM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

... BitBlt() needs to specify 0x0 for the source bitmap coordinates
not sure what you mean.

In your original code:

::BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
  ps.rcPaint.right - ps.rcPaint.left,
  ps.rcPaint.bottom - ps.rcPaint.top,
  Form1->hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);


You were setting the nXSrc/nYSrc parameters to ps.rcPaint.left/top instead
of 0/0, respectively.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 20, 2015 2:38 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

You were setting the nXSrc/nYSrc parameters to ps.rcPaint.left/top instead
of 0/0, respectively.

Nevermind this point, I just realized what the original code was doing. If the clipping rectangle does not take the entire client area into account, nXDest/nYDest and nXSrc/nYSrc should match since the bitmap and window are the same size and you don't want the bitmap drawing to be shifted incorrectly.

--
Remy Lebeau (TeamB)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 20, 2015 2:39 PM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

the need for this in-memory bitmap is dictated by project design:
it's dynamically (and slowly) created image only part of which is
occasionally being shown on that layered window.

Then I would suggest drawing onto a separate Graphics::Bitmap instead of
an in-memory HDC, and then DrawImage() that Bitmap onto WM_PAINT's HDC when
needed.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 21, 2015 9:01 AM   in response to: Boba ½° in response to: Boba ½°
"Remy Lebeau (TeamB)" wrote in message
So double-check your BMP file, make sure it really is using PURE
red (255,0,0) pixels. When I created a red bitmap with mspaint,
the resulting pixels were not PURE red (237,28,36),

right on it!

all pixels are pure red: in the file AND in the memory on hdcMem,
I've checked'em with GetPixel(hdcMem,x,y) - it returns 0x000000ff.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 21, 2015 10:50 AM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

all pixels are pure red: in the file AND in the memory on hdcMem,
I've checked'em with GetPixel(hdcMem,x,y) - it returns 0x000000ff.

I don't know what else to tell you. The following code works perfectly fine
for me when using a pure-red 200x200px 24bit BMP file. The layered window
is fully transparent as expected, and when changing the RGB on SetLayeredWindowAttributes()
then the window appears red translucent as expected:

//---------------------------------------------------------------------------
 
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <gdiplus.h>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
    TButton *Button1;
    TButton *Button2;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall Button2Click(TObject *Sender);
private:	// User declarations
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    HWND hWndTst;
    HBITMAP hbmp, hbmp0;
    HDC hdcScr;
public:		// User declarations
    HDC hdcMem;
    __fastcall TForm1(TComponent* Owner);
    __fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    if( Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) 
!= Gdiplus::Ok )
    {
        ShowMessage("GdiplusStartup");
    }
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
    Gdiplus::GdiplusShutdown( gdiplusToken );
}
//---------------------------------------------------------------------------
LRESULT CALLBACK WndProcTst(HWND hWnd, UINT uMsg, WPARAM wPrm, LPARAM lPrm)
{
    HDC hdc;
    PAINTSTRUCT ps;
    switch( uMsg )
    {
        case WM_CREATE:
        case WM_DESTROY:
            return 0;
        case WM_PAINT:
            hdc = ::BeginPaint(hWnd, &ps);
            if( hdc )
            {
                ::BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
                    ps.rcPaint.right - ps.rcPaint.left,
                    ps.rcPaint.bottom - ps.rcPaint.top,
                    Form1->hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
                /*
                ::InflateRect(&ps.rcPaint, -40, -40);
                HBRUSH hBrush = ::CreateSolidBrush( RGB(0xff,0,0) );
                ::FillRect(hdc, &ps.rcPaint, hBrush);
                ::DeleteObject(hBrush);
                */
            }
            ::EndPaint(hWnd, &ps);
            return 0;
    }//switch( uMsg ){
    return ::DefWindowProc(hWnd, uMsg, wPrm, lPrm);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    WNDCLASSEX wndcls;
    ::ZeroMemory( &wndcls, sizeof(wndcls) );
    wndcls.cbSize = sizeof(wndcls);
    //wndcls.lpfnWndProc = DefWindowProc;
    wndcls.lpfnWndProc = WndProcTst; //need to process WM_PAINT
    wndcls.hInstance = HInstance;
    wndcls.lpszClassName = TEXT("wndclstst");
    if( !::RegisterClassEx(&wndcls) )
    {
        ShowMessage("RegisterClass");
        return;
    }
    hWndTst = ::CreateWindowEx(WS_EX_NOACTIVATE|WS_EX_LAYERED,
        TEXT("wndclstst"), NULL,
        WS_VISIBLE|WS_POPUP, 100, 100, 200, 200,
        NULL, NULL, HInstance, NULL );
    if( !hWndTst )
    {
        ShowMessage( "CreateWindowEx" );
        return;
    }
    hdcScr = ::GetDC(NULL);
    hdcMem = ::CreateCompatibleDC(hdcScr);
    hbmp = ::CreateCompatibleBitmap(hdcScr, 200, 200);
    if( !hbmp )
    {
        ShowMessage( "CreateCompatibleBitmap" );
        return;
    }
    hbmp0 = (HBITMAP)::SelectObject( hdcMem, hbmp );
    Gdiplus::Bitmap bmp(L"tst.bmp"); //24-bit map
    Gdiplus::Graphics grfx(/*Canvas->Handle*/hdcMem);//uncomment to see bmp
    if(grfx.DrawImage(&bmp, 0, 0) != Gdiplus::Ok)
    {
        ShowMessage( "DrawImage" );
        return;
    }
    if( !::SetLayeredWindowAttributes(hWndTst, RGB(0xff,0,0), 0x80, LWA_COLORKEY|LWA_ALPHA) 
)
    {
        ShowMessage( "SetLayout "+IntToStr((int)::GetLastError()) );
        return;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    ::SelectObject( hdcMem, hbmp0 );
    if(hbmp) ::DeleteObject(hbmp);
    if(hdcMem) ::DeleteDC(hdcMem);
    if(hWndTst) ::DestroyWindow(hWndTst);
    ::UnregisterClass(TEXT("wndclstst"), HInstance);
    if(hdcScr) ::ReleaseDC(NULL, hdcScr);
}
//---------------------------------------------------------------------------


If it is not working for you, then I have to suspect your BMP file is not
correct (I will send you a working BMP, if you need it). I still suggest
you use the other code I gave you, though. Use an in-memory Graphics::Bitmap
to do your drawing and just draw it as-is directly onto the HDC that BeginPaint()
provides, no need for a separate in-memory HDC.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 21, 2015 1:34 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
"Remy Lebeau (TeamB)" wrote in message
news:724491 at forums dot embarcadero dot com...

... I have to suspect your BMP file is not correct

the file is just fine; it is GDI+.

I will send you a working BMP, if you need it.

please do not. Many thanks for all your suggestions.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SetLayeredWindowAttributes fails with no error reported [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 21, 2015 1:52 PM   in response to: Boba ½° in response to: Boba ½°
Boba wrote:

the file is just fine

Can you provide the actual file you are using so I can check it? I have
posted my test BMP file to the Attachments forum for you.

--
Remy Lebeau (TeamB)
Boba ½°

Posts: 73
Registered: 12/19/03
Re: UpdateLayeredWindow fails with no error reported
Click to report abuse...   Click to reply to this thread Reply
  Posted: May 14, 2015 8:55 AM   in response to: Boba ½° in response to: Boba ½°
"Boba ½°" wrote in message news:723841 at forums dot embarcadero dot com...
BlankDear Reader; ...

I didn't write "BlankDear"
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02