[Solved] Problem with Controls being Unselectable in Win 10 Transparent Forms ! lazarus / 34-Windows ---------------------------------------------------------------------- loaded · 2022-12-12 08:26 Hi All, I have an application that contains a form where I apply the transparency process due to some needs. I wrote this application in "win7 prof" operating system and used it without any problems. Now, when I want to use the same application in "Win10 enterprise" operating system, I saw that some controls in the Form do not work with mouse selection and click. Attached is a small application that I try to explain the situation. In other words, the form works fine in normal condition, but after transparency, especially the checkbox becomes unselectable with the mouse. But it can be controlled with the tab key. I would be very pleased if you share your views and suggestions on the subject. Respects. ---------------------------------------------------------------------- loaded · 2022-12-20 11:42 Disabling the "Use manifest resource" option from the project options solves the problem. But this time access to form background is disabled. Now; I'm looking for a way to make the form itself transparent, except for the components in the form, without using any windows api. By the way, the controls on the back of the form should also be accessible! ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 12:11 Maybe my windows example you can convert to crosscompile, instead of try making the form transparent, what would end in transparent controls, cut out what you not want on your form from the form itself. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormCreate(Sender: TObject);  var    LeftRgn : HRGN;    RightRgn : HRGN;    NewRgn : HRGN;  begin        LeftRgn  := CreateEllipticRgn(10,10,width div 2, height-10);        RightRgn := CreateEllipticRgn(width div 2, 10, width-10, height-10);        NewRgn := CreateRectRgn(0,0,0,0);        CombineRgn(NewRgn,LeftRgn,RightRgn,RGN_OR);        DeleteObject(LeftRgn);        DeleteObject(RightRgn);        SetWindowRgn(handle,NewRgn,false);  end; ---------------------------------------------------------------------- loaded · 2022-12-20 13:26 Thank you very much KodZwerg for the answer, This may be a solution, but it seems like it will be a bit of a hassle... ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 13:41 In Delphi I can do this, have no Lazarus right here to test. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm7.FormCreate(Sender: TObject);var  AControl : TControl;  A, Margin, X, Y, CtlX, CtlY : Integer;  FullRgn, ClientRgn, CtlRgn : THandle;begin  Margin := ( Width - ClientWidth ) div 2;  //First, get form region  FullRgn := CreateRectRgn(0, 0, Width, Height);  //Find client area region  X := Margin;  Y := Height - ClientHeight - Margin;  ClientRgn := CreateRectRgn( X, Y, X + ClientWidth, Y + ClientHeight );  //'Mask' out all but non-client areas  CombineRgn( FullRgn, FullRgn, ClientRgn, RGN_DIFF );   //Now, walk through all the controls on the form and 'OR' them  // into the existing Full region.  for A := 0 to ControlCount - 1 do begin    AControl := Controls[A];  if ( AControl is TWinControl ) or ( AControl is TGraphicControl ) or ( AControl is TControl )        then with AControl do begin      if Visible then begin        CtlX := X + Left;        CtlY := Y + Top;      CtlRgn := CreateRectRgn( CtlX, CtlY, CtlX + Width, CtlY + Height );        CombineRgn( FullRgn, FullRgn, CtlRgn, RGN_OR );      end;  end;  end;  //When the region is all ready, put it into effect:  SetWindowRgn(Handle, FullRgn, TRUE);  DeleteObject(ClientRgn);  DeleteObject(FullRgn);  DeleteObject(CtlRgn);end;Added two pictures, one of the form designer to show what i created and another when you execute the app. ---------------------------------------------------------------------- loaded · 2022-12-20 13:55 Firstly ; Thank you very much for taking your precious time, effort and preparing an example. When I run it in Lazarus, a different view is created. -There is no frame for the form -There is a shift in control positions. Again ; A very good example to start with. After that, I'll do trial and error. I don't want to tire you out any more. Respects. ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 14:04 Quote from: loaded on December 20, 2022, 02:55:48 pmFirstly ; Thank you very much for taking your precious time, effort and preparing an example. When I run it in Lazarus, a different view is created. -There is no frame for the form -There is a shift in control positions. Again ; A very good example to start with. After that, I'll do trial and error. I don't want to tire you out any more. Respects. You are welcome, I do not exactly know in what Lazarus is doing different than Delphi does, since all I use is Windows API... very strange  Maybe a Lazarus LCL mod can say what I do wrong in belonging to Controls and Positioning, I mean what cause that big shifting and taking Caption away...  Best of Luck ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 15:13 I am now on a machine with Lazarus 2.2.4 (rev lazarus_2_2_4) FPC 3.2.2 x86_64-win64-win32/win64 I did found the problem, to me it looks like that this is a bug or on purpose interpreted like that? ClientWidth and ClientHeight are same as Width and Height so my calculation based on that area is wrong since the LCL gives me back not the correct needed value. Top, Left, Width, Height, those are the dimensions of a full formular + OS individual border/shadow ClientWidth and ClientHeight is the area inside of that full formular to us developers to play with, outside of that begins the world of NC (NonClient). I will look if I can come up with own method for ClientWidth and ClientHeight calculation, when that is fixed my above code will work on Lazarus/LCL. ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 15:16 Here I show you the result when I do insert this line after "ClientRgn := CreateRectRgn( X, Y, X + Self.ClientWidth, Y + Self.ClientHeight );" Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   ShowMessage(Format('Left: %d Top: %d Width: %d Height %d' + sLineBreak +                     'Width: %d Height: %d',                     [X, Y, X + Self.ClientWidth, Self.ClientHeight, Self.Width, Self.Height]));First the Delphi Result second the Lazarus Results, both compiler for Windows as Target. //edit, sorry, I made a mistake, on what is called left on picture means top and vice versa. I apology. (above code now corrected) ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 15:43 Switching to "Self.ClientRect.Width" or "Self.ClientRect.Height" does not help, it gives also wrong value back on LCL, something I do wrong... ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 15:55 To Answer myself, the LCL just does not include what I need. Lazarus_FAQ ---------------------------------------------------------------------- loaded · 2022-12-20 16:01 Quote from: KodeZwerg on December 20, 2022, 04:55:14 pmTo Answer myself, the LCL just does not include what I need. Lazarus_FAQ It doesn't matter whether KodeZwerg codes work or not. Thank you very much for your efforts, your effort is more valuable than anything else. I'll handle the rest. Besides, I owe you a coffee. Respects. ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 17:25 Without intense testing, this I come up with, hopeful works for all Lazarus Editions same on Windows. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormCreate(Sender: TObject);var  AControl : TControl;  A, Margin, X, Y, CtlX, CtlY : Integer;  FullRgn, ClientRgn, CtlRgn : THandle;  cW, cH, cWidth, cHeight: LongInt;  ClientRec: TRect;begin  Windows.GetClientRect(Self.Handle, ClientRec);  cW := GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXFOCUSBORDER);  cH := GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CYFOCUSBORDER) + GetSystemMetrics(SM_CYCAPTION);  cWidth := ClientRec.Width - cW;  cHeight:= ClientRec.Height - cH;  Margin := (Self.Width - cWidth) div 2;  //First, get form region  FullRgn := CreateRectRgn(0, 0, Self.Width + cW, Self.Height + cH);  //Find client area region  X := Margin;  Y := Self.Height - cHeight - Margin - GetSystemMetrics(SM_CYBORDER);  ClientRgn := CreateRectRgn( X, Y, X + cWidth + cW, Y + cHeight + cH);//'Mask' out all but non- client areas  CombineRgn( FullRgn, FullRgn, ClientRgn, RGN_DIFF );  //Now, walk through all the controls on the form and 'OR' them  // into the existing Full region.  for A := 0 to ControlCount - 1 do begin    AControl := Controls[A];    if ( AControl is TWinControl ) or ( AControl is TGraphicControl ) or ( AControl is TControl )        then with AControl do begin      if Visible then begin        CtlX := X + Left;        CtlY := Y + Top;        CtlRgn := CreateRectRgn( CtlX, CtlY, CtlX + Width + GetSystemMetrics(SM_CXEDGE), CtlY + Height + GetSystemMetrics(SM_CYEDGE) );        CombineRgn( FullRgn, FullRgn, CtlRgn, RGN_OR );      end;    end;  end;  //When the region is all ready, put it into effect:  SetWindowRgn(Handle, FullRgn, TRUE);  DeleteObject(ClientRgn);  DeleteObject(FullRgn);  DeleteObject(CtlRgn);end;There are still hardcoded numbers inside for what I do need to get a good GetSystemMetrics(), this is just a alpha working release. Please let me know if this works for you. ---------------------------------------------------------------------- loaded · 2022-12-20 18:08 Quote from: KodeZwerg on December 20, 2022, 06:25:34 pmPlease let me know if this works for you. All I'm looking for is; It was to be able to see and check the background and use the controls on the forum. Yes it worked now. Thank you very much. ---------------------------------------------------------------------- KodeZwerg · 2022-12-20 18:22 Ah, now I see what you are doing. You are welcome ---------------------------------------------------------------------- KodeZwerg · 2022-12-21 03:44 Updated to be able to work better for different BorderStyle settings. Make this method part of your form and call it in OnCreate and OnResize. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.MakeTransparent;var  AControl: TControl;  A, Margin, X, Y, CtlX, CtlY: Integer;  FullRgn, ClientRgn, CtlRgn: THandle;  cXBorder, cYBorder, cWidth, cHeight: LongInt;begin  // calculate different border styles  case Self.BorderStyle of    bsDialog:      begin      cXBorder := 0;        cYBorder := GetSystemMetrics(SM_CYCAPTION);    end;    bsNone:      begin        cXBorder := GetSystemMetrics(SM_CXBORDER);        cYBorder := GetSystemMetrics(SM_CYBORDER);      end;    bsSingle:      begin      cXBorder := 0;        cYBorder := GetSystemMetrics(SM_CYCAPTION);    end;    bsSizeable:      begin        cXBorder := GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXFOCUSBORDER);        cYBorder := GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CYFOCUSBORDER) + GetSystemMetrics(SM_CYCAPTION);    end;    bsSizeToolWin:      begin        cXBorder := GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXFOCUSBORDER);        cYBorder := GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CYFOCUSBORDER) + GetSystemMetrics(SM_CYCAPTION);    end;    bsToolWindow:      begin        cXBorder := 0;        cYBorder := GetSystemMetrics(SM_CYCAPTION);      end;  end;   // set client dimension  cWidth := Self.ClientRect.Width - cXBorder;  cHeight:= Self.ClientRect.Height - cYBorder;  Margin := (Self.Width - cWidth) div 2;   // get form and client area region  X := Margin;  case Self.BorderStyle of    bsDialog:      begin        FullRgn := CreateRectRgn(0, 0, Self.Width + cXBorder + GetSystemMetrics(SM_CXDLGFRAME), Self.Height + cYBorder + GetSystemMetrics(SM_CYDLGFRAME));        Y := Self.Height - cHeight - Margin + GetSystemMetrics(SM_CYDLGFRAME);        ClientRgn := CreateRectRgn(X, Y, X + cWidth + cXBorder + GetSystemMetrics(SM_CXDLGFRAME), Y + cHeight + cYBorder + GetSystemMetrics(SM_CYDLGFRAME));      end;    bsNone:      begin      FullRgn := CreateRectRgn(0, 0, Self.Width + cXBorder, Self.Height + cYBorder);        Y := Self.Height - cHeight - Margin - GetSystemMetrics(SM_CYBORDER);        ClientRgn := CreateRectRgn(X, Y, X + cWidth + GetSystemMetrics(SM_CXBORDER), Y + cHeight + GetSystemMetrics(SM_CYBORDER));      end;    bsSingle:      begin      FullRgn := CreateRectRgn(0, 0, Self.Width + cXBorder + GetSystemMetrics(SM_CXDLGFRAME), Self.Height + cYBorder + GetSystemMetrics(SM_CYDLGFRAME));        Y := Self.Height - cHeight - Margin + GetSystemMetrics(SM_CYDLGFRAME);        ClientRgn := CreateRectRgn(X, Y, X + cWidth + cXBorder + GetSystemMetrics(SM_CXDLGFRAME), Y + cHeight + cYBorder + GetSystemMetrics(SM_CYDLGFRAME));      end;    bsSizeable:      begin        FullRgn := CreateRectRgn(0, 0, Self.Width + cXBorder, Self.Height + cYBorder);        Y := Self.Height - cHeight - Margin - GetSystemMetrics(SM_CYBORDER);        ClientRgn := CreateRectRgn( X, Y, X + cWidth + cXBorder, Y + cHeight + cYBorder);      end;    bsSizeToolWin:      begin        FullRgn := CreateRectRgn(0, 0, Self.Width + cXBorder, Self.Height + cYBorder);        Y := Self.Height - cHeight - Margin - GetSystemMetrics(SM_CYBORDER);      ClientRgn := CreateRectRgn( X, Y, X + cWidth + cXBorder, Y + cHeight + cYBorder);      end;    bsToolWindow:      begin        FullRgn := CreateRectRgn(0, 0, Self.Width + cXBorder + GetSystemMetrics(SM_CXDLGFRAME), Self.Height + cYBorder + GetSystemMetrics(SM_CYDLGFRAME));        Y := Self.Height - cHeight - Margin + GetSystemMetrics(SM_CYDLGFRAME);        ClientRgn := CreateRectRgn(X, Y, X + cWidth + cXBorder + GetSystemMetrics(SM_CXDLGFRAME), Y + cHeight + cYBorder + GetSystemMetrics(SM_CYDLGFRAME));      end;  end;   // 'Mask' out all but non-client areas  CombineRgn(FullRgn, FullRgn, ClientRgn, RGN_DIFF);   // Now, walk through all the controls on the form and 'OR' them into the existing Full region.  for A := 0 to Pred(ControlCount) do    begin      AControl := Controls[A];      if ((AControl is TWinControl) or (AControl is TGraphicControl) or (AControl is TControl)) then        if AControl.Visible then          begin            CtlX := X + AControl.Left;            CtlY := Y + AControl.Top;            case Self.BorderStyle of              bsDialog:                begin                  CtlRgn := CreateRectRgn(CtlX + GetSystemMetrics(SM_CXDLGFRAME), CtlY, CtlX + AControl.Width + GetSystemMetrics(SM_CXDLGFRAME), CtlY + AControl.Height);                end;              bsNone:              begin                  CtlRgn := CreateRectRgn(CtlX, CtlY, CtlX + AControl.Width, CtlY + AControl.Height);                end;            bsSingle:                begin                  CtlRgn := CreateRectRgn(CtlX + GetSystemMetrics(SM_CXDLGFRAME), CtlY, CtlX + AControl.Width + GetSystemMetrics(SM_CXDLGFRAME), CtlY + AControl.Height);                end;              bsSizeable:              begin                  CtlRgn := CreateRectRgn(CtlX, CtlY, CtlX + AControl.Width + GetSystemMetrics(SM_CXEDGE), CtlY + AControl.Height + GetSystemMetrics(SM_CYEDGE));                end;              bsSizeToolWin:                begin                  CtlRgn := CreateRectRgn(CtlX, CtlY, CtlX + AControl.Width + GetSystemMetrics(SM_CXEDGE), CtlY + AControl.Height + GetSystemMetrics(SM_CYEDGE));                end;              bsToolWindow:                begin                  CtlRgn := CreateRectRgn(CtlX + GetSystemMetrics(SM_CXDLGFRAME), CtlY, CtlX + AControl.Width + GetSystemMetrics(SM_CXDLGFRAME), CtlY + AControl.Height);                end;            end;            CombineRgn(FullRgn, FullRgn, CtlRgn, RGN_OR);          end;    end;   // When the region is all ready, put it into effect:  SetWindowRgn(Handle, FullRgn, TRUE);   // clean up the mess  DeleteObject(ClientRgn);  DeleteObject(FullRgn);  DeleteObject(CtlRgn);end;Enjoy transparent forms for Windows ---------------------------------------------------------------------- loaded · 2022-12-21 04:59 Yes this code is better. I can't thank you enough for your hard work. Respects.