There is a PNG image that I put on the form. Naturally, before this form do "puff". Then I call UpdateLayeredWindow with all the necessary parameters. Everything is wonderful. Both the form is shown and PNG is applied as it should be.

BUT

One day, I decided to print something like Caption for this form. I just brought the text to a pre-prepared bitmap, and then again used UpdateLayeredWindow . To my surprise, the displayed text became “transparent” for clicks. That is, if my window is over any text editor, then when you hover the mouse over the text, the cursor takes the form as you type text.

Actually, the question is : is it really possible to display the text correctly on the Layered-window or is it impossible in principle. Note: GDI + does not even consider.

An example of how this looks is given below.
enter image description here

The brown background is my PNG image. If you need to - tell me, I'll post it here.

Decision
Perhaps there is a better solution to the problem described, but so far I have found only that.
Suppose that we have a ready bitmap bitmap and it also has transparency. Then we load this bitmap into an instance of the TBitmap class and make a copy of it onto a third-party bitmap. After that, we display text, pictures, etc. on the made copy, then we call the CopyAlphaChannel procedure to restore the transparency of the pixels overwritten by the output of text, pictures, etc. In the end, we need to copy the resulting image to the original bitmap and pass it as one of the parameters for the UpdateLayeredWindow function.

Sample code:

 procedure TForm1.Button1Click(Sender: TObject); var OutBmp, B: TBitmap; begin // Здесь уже должны быть сделаны все приготовления для вывода OutBmp с помощью функции UpdateLayeredWindow // Создаем наш битмап для вывода текста B := TBitmap.Create; B.Width := OutBmp.Width; B.Height := OutBmp.Height; B.PixelFormat := pf32bit; // Делаем копию оригинального битмапа B.Canvas.Draw(0, 0, OutBmp); // Выводим текст, например B.Canvas.Brush.Style := bsClear; B.Canvas.Font.Style := [fsBold]; B.Canvas.Font.Color := clYellow; B.Canvas.Font.Size := 11; B.Canvas.TextOut(4, 4, 'Simple txt string'); B.Canvas.Brush.Style := bsSolid; // Собственно, цель этого куска кода - восстановление затертой альфы CopyAlphaChannel(OutBmp, B); // Копируем буфер обратно на оригинал OutBmp.Canvas.Draw(0, 0, B); B.Free; // Далее OutBmp передается как один из параметров для UpdateLayeredWindow end; 

Now it's up to the alpha channel copy procedure:

 procedure CopyAlphaChannel(ABmpIn, ABmpOut: TBitmap); type TRGBAArray = array[Word] of TRGBQuad; PRGBAArray = ^TRGBAArray; var X: Integer; Y: Integer; RowIn: PRGBAArray; RowOut: PRGBAArray; begin // ABmpIn - битмап, содержащий альфа-канал if not Assigned(ABmpIn) or not Assigned(ABmpOut) then Exit; for Y:=0 to ABmpIn.Height - 1 do begin RowIn := ABmpIn.ScanLine[Y]; RowOut := ABmpOut.ScanLine[Y]; for X:=0 to ABmpIn.Width - 1 do RowOut[X].rgbReserved := RowIn[X].rgbReserved; end; end; 

As a result, we get the following image:
enter image description here

  • You want to drag a window for this text? A little confusing question. You are confused that the cursor is changing, or the transparency for clicks. And what does it mean to display the text correctly ?. Add text to the png itself, as an option if there is no dynamic information there and you don’t need to do anything with it. - teran
  • @teran, yes, I would like to “drag” the form across the screen for this text, therefore adding text to the PNG source file is not what is required. Correctly displaying text means displaying text on the Layered window as it appears on a normal window — that is, so that the text is not transparent to mouse clicks. In the picture in question, if you click on the text, the Layered window will lose focus, and the IDE code editor window will receive focus. - Dima
  • You need exactly this question and ask. Now from reading the question, it seems that you have a problem in the graphics, and not in the interaction of the mouse with your window. You and the picture obviously resulted in this (graphic) problem. - mega
  • @mega may have a really messy problem. I apologize. However, do you have any solutions to the problem? - Dima
  • for transparent windows so conceived, here's a similar question on en.so: stackoverflow.com/questions/14086006/… - mega

1 answer 1

Actually, the question is: is it really possible to display the text correctly on the Layered-window or is it impossible in principle.

Regarding the red background of the text, this is completely solvable, regardless of the type of transparency: just before displaying the text, set the transparent background in hdc via SetBkMode(hdc, TRANSPARENT) .

@mega, the question on the link does not apply to my problem. I got the impression that the text displayed on the bitmap simply overwrites the alpha of the bitmap and turns out to be “transparent” for clicks, while the rest of the form behaves as usual. Only it is not clear to me how not to overwrite the alpha value of the pixels under the text.

The link gives a solution just when you need to disable the Windows feature with transparency for mouse clicks. This feature allows you to make forms of arbitrary shape, and they harmoniously fit into the Windows interface.

When outputting to a form, it is necessary to write a unit instead of zero in the alpha channel. This will not affect the transparency of the text, you will not even see this percentage of the percentage, but this unit will return functionality for the mouse.

Zero in alpha channel expose standard GDI functions (TextOut, DrawText, etc.).

I would try to do this:

  1. We are preparing the DIB-section of the size you need, on which you will draw.
  2. Fill it with a neutral color
  3. We write the necessary text in it
  4. Pass through the memory DIB'a and expose everywhere alpha = 1
  5. Print the DIB on the form using AlphaBlend (choose the transparency key that was used in step 2)

As far as I know, GDI +, which you immediately dismounted, is able to do similar things; in this case, a deep knowledge of GDI is not required from the programmer.

Those. if the question was “how would I do it” and not “how does it work”, then I would probably still go back to GDI +.

ps: by the way as far as I understand, you do not want to draw a transparent text? So you do not need to put one in the alpha channel, and 255.

  • Yes, I also thought about the restoration of alpha yesterday and nevertheless solved this question. In any case, for my needs, the solution is quite sufficient. Although I am sure that if you think more, you can optimize the code that is in my question. I will accept your answer, because some thoughts in it and hit on the answer. ZY I cannot raise the rating of your answer due to limitations, excuse me)) - Dima
  • For those interested in the problem - the answer is added to the "body" of the question. There is also some code. - Dima