0

I want to create/open a window with transparent background.

I want to know for:

  • Using semi-transparent images

  • Rounded corners

  • I want to see the desktop behind the app

  • Fading the app in and out

Is it possible to show HTA with transparent background? How to do that?

user692942
  • 16,398
  • 7
  • 76
  • 175
  • I found https://batch.xoo.it/t5516-Transparent-HTA.htm BUT I did not tested it - I don't speak Italien – user11714941 Oct 14 '21 at 06:09
  • And I found https://www.tek-tips.com/viewthread.cfm?qid=1441484 he writes about AutoHotKey "AHK" ? and I think with "bugy" he means not using 3rdParty tools; I think he means using software that makes the windows transparent but not keeping the content untransparent. Anywhere I found 3 names of software which can make the windows transparent but as I checked one time without being able to keep the content untransparent. – user11714941 Oct 14 '21 at 06:09
  • I don't want to write a renderer which creates for every px a new hta or a new window.modularPopup – user11714941 Oct 14 '21 at 06:10
  • Does this answer your question? [Is there a way to set the alpha channel of the GUI in a HTA to get it transparent?](https://stackoverflow.com/q/40059020/692942) – user692942 Oct 14 '21 at 06:42
  • Basically, the answer is no. – user692942 Oct 14 '21 at 06:43
  • @user11714941 why are you using an HTA in the first place? It's not just that IE11 all relevant technologies are not just obsolete but actually missing from supported Windows versions. You can now create full desktop apps using Electron (like VS Code and Slack clients). All the things you asked are available without any tricks, just by using CSS, Bootstrap or any other CSS framework of your choice. Simply googling for `Electron transparent` returned [this as the first result](https://ourcodeworld.com/articles/read/315/how-to-create-a-transparent-window-with-electron-framework) – Panagiotis Kanavos Nov 30 '21 at 13:37
  • @PanagiotisKanavos Correction... [IE 11 is not missing from any version of Windows](https://superuser.com/a/1746047/1283806), but that is irrelevant in regards to HTAs as they are not dependent on IE. They use the same engine as IE (MSHTML), but that engine remains even if IE is uninstalled. Also, the OP may have wanted something more light-weight than Electron. – LesFerch Mar 11 '23 at 18:06
  • @LesFerch that answer contradicts itself - IE isn't missing, but trying to use it redirects to a Chromium browser because it's actually missing. [Sure, there are remnants that are actively being removed](https://techcommunity.microsoft.com/t5/windows-it-pro-blog/internet-explorer-11-desktop-app-retirement-faq/ba-p/2366549). If someone wants to build something like an HTA in 2023, a plain old HTML file with Javascript is more powerful. – Panagiotis Kanavos Mar 13 '23 at 08:32
  • @PanagiotisKanavos There is no contradiction. Please read the information at the [provided link](https://superuser.com/questions/1719397/run-install-internet-explorer-on-windows-11/1746047#1746047). A plain old HTML file with JavaScript, running in a browser, has no direct access to the file system, registry, etc. therefore, it is not a substitute for an HTA. – LesFerch Mar 13 '23 at 12:56

2 Answers2

2

Well, the answer is yes, but only with the help of an ActiveX control. There is an ActiveX control called DynamicWrapperX that will allow you to use the Win32 API in your HTA. I've done this myself. Fair warning though - the DLL is falsely flagged as malware (or a PUP) by some scanners. I've been using it since I think 2015, but of course you need to decide for yourself whether you want to use it.

If you do use it, you can make your entire app window transparent like this:

<!doctype html>
<HTA:APPLICATION
  APPLICATIONNAME="Transparent App"
  BORDER="dialog"
  BORDERSTYLE="thin"
  SINGLEINSTANCE="yes"
  CONTEXTMENU="no"
  ID="HTA"
  INNERBORDER="no"
  MAXIMIZEBUTTON="no"
  NAVIGABLE="no"
  SCROLL="yes"
  SHOWINTASKBAR="yes"
/>
<html lang="en-US">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=9" />
  <title>Loading...</title>
</head>
<body>
  <script>
    var dx;

    function setWindowTransparency(handle, alpha) {
      if (!dx || handle === null || isNaN(handle) || isNaN(alpha)) return false;

      // Alpha is 0-100
      if (alpha < 0) alpha = 0;
      if (alpha > 100) alpha = 100;

      // Convert 0-100 to 0-255
      alpha = parseInt(2.55 * alpha);

      // Make this a layered window 
      dx.SetWindowLong(handle, -20, 0x80000);

      // Set the opacity of the layered window
      dx.SetLayeredWindowAttributes(handle, 0, alpha, 0x2);

      return true;
    }

    function animateWindowTransparency(handle, min, max, direction) {
      if (!dx || handle === null || isNaN(handle) || isNaN(max) || isNaN(min)) return false;

      // Defaults to fading out then in (-1 = out; 1 = in)
      if (!direction) direction = -1;

      var alpha = (direction === -1) ? max : min;
      
      (function animate() {
        alpha += (direction === -1) ? -1 : 1;

        if (direction === -1 && alpha < min) {
          alpha = min;
          direction = 1;
        } else if (direction === 1 && alpha > max) {
          alpha = max;
          direction = -1;
        }

        setWindowTransparency(handle, alpha);

        // Adjust the timeout delay slightly if it's too fast.
        // 10ms - 30ms is a nice range
        setTimeout(animate, 10);
      })();
    }

    (function main() {
      var HTA = document.getElementById('HTA');

      if (!HTA) return setTimeout(main, 33);

      // IE9 engine needs the title set programatically
      document.title = HTA.applicationName;

      // Load DynamicWrapperX
      dx = new ActiveXObject('DynamicWrapperX');

      // Register the APIs we need for transparency
      // This means input=window handle, long, long; return=long
      dx.Register('user32', 'SetWindowLong', 'i=hll', 'r=l');

      // input=window handle, long, long, long; return=long
      dx.Register('user32', 'SetLayeredWindowAttributes', 'i=hlll', 'r=l');

      // We'll need the FindWindow API to find our HTA's window handle
      dx.Register('user32', 'FindWindow', 'i=ss', 'r=h');

      (function getHandle() {
        // Now to use it, we need to get our HTA's window handle.
        // This will search all open windows matching this class and title
        var handle = dx.FindWindow('HTML Application Host Window Class', document.title);

        if (!handle) return setTimeout(getHandle, 33);

        // Now that we have the handle, set the transparency to 65%
        // setWindowTransparency(handle, 65);

        // Or animate the window transparency between 10% - 50%
        animateWindowTransparency(handle, 10, 50);
      })();
    })();
  </script>
</body>
</html>

Update 3/12/2023 Here's how you can have a transparent image show fullscreen on your HTA. I suggest using an obscure color like #010203 that isn't likely to be used elsewhere in your app, to prevent transparency where you didn't want it.

<!doctype html>
<HTA:APPLICATION
  APPLICATIONNAME="Transparent App"
  BORDER="none"
  SINGLEINSTANCE="yes"
  CONTEXTMENU="no"
  ID="HTA"
  INNERBORDER="no"
  MAXIMIZEBUTTON="no"
  NAVIGABLE="no"
  SCROLL="yes"
  SHOWINTASKBAR="yes"
/>
<html lang="en-US">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=9" />
  <title>Loading...</title>
  <style>
    html, body {
      min-height: 100%;
      background: #010203;
      background-size: 100% 100%;
      overflow: hidden;
    }
    .widgets {
        position: fixed;
        top: 12px;
        right: 16px;
        bottom: 0;
    }
    .widget {
        position: relative;
        width: 100%;
        min-width: 150px;
        min-height: 150px;
        border: 1px solid #000;
        border-radius: 12px;
        margin-bottom: 10px;
        overflow: hidden;
    }
    .widget > img {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 100%;
        transform: translate(-50%, -50%);
    }
  </style>
</head>
<body>
  <div class="widgets">
    <div class="widget">
        <img src="https://i.ibb.co/19s2kCC/TBGButterfly1.png" alt="" />
    </div>
    <div class="widget">
        <img src="https://i.ibb.co/CKS8GZZ/TBGCalvin-Hobbes1.png" alt="" />
    </div>
    <div class="widget">
        <img src="https://i.ibb.co/Zgpmd0N/TBGCat1.png" alt="" />
    </div>
  </div>
  <script>
    var dx;

    function hexToLong(hex, mode) {
      var c, n, tmp = "";

      hex = hex.toString().replace(/[^a-f0-9]/ig, "");

      if (!mode) mode = "rgb";

      if (hex.length === 3) {
        c = -1;
        n = 3;

        while (++c < n) {
          tmp += hex.charAt(c) + hex.charAt(c);
        }

        hex = tmp;
      }

      if (hex.length !== 6) return parseInt(hex, 16);

      var hexR = hex.substr(0, 2),
          hexG = hex.substr(2, 2),
          hexB = hex.substr(4, 2);

      switch(mode.toLowerCase()) {
        case "bgr":
          return parseInt(hexB + hexG + hexR, 16);
        case "brg":
          return parseInt(hexB + hexR + hexG, 16);
        case "gbr":
          return parseInt(hexG + hexB + hexR, 16);
        case "grb":
          return parseInt(hexG + hexR + hexB, 16);
        case "rbg":
          return parseInt(hexR + hexB + hexG, 16);
        default:
          return parseInt(hexR + hexG + hexB, 16);
      }
    }

    function setWindowTransparencyKey(handle, color) {
      if (!dx || handle === null || isNaN(handle) || typeof color === "undefined") return false;
      if (typeof color === "string") color = hexToLong(color, "BGR");
      if (color === false) color = -2;

      dx.SetWindowLong(handle, -20, 0x80000);
      dx.SetLayeredWindowAttributes(handle, color, 0, 0x1);

      return true;
    }

    function setWindowTransparency(handle, alpha) {
      if (!dx || handle === null || isNaN(handle) || isNaN(alpha)) return false;

      // Alpha is 0-100
      if (alpha < 0) alpha = 0;
      if (alpha > 100) alpha = 100;

      // Convert 0-100 to 0-255
      alpha = parseInt(2.55 * alpha);

      // Make this a layered window 
      dx.SetWindowLong(handle, -20, 0x80000);

      // Set the opacity of the layered window
      dx.SetLayeredWindowAttributes(handle, 0, alpha, 0x2);

      return true;
    }

    function animateWindowTransparency(handle, min, max, direction) {
      if (!dx || handle === null || isNaN(handle) || isNaN(max) || isNaN(min)) return false;

      // Defaults to fading out then in (-1 = out; 1 = in)
      if (!direction) direction = -1;

      var alpha = (direction === -1) ? max : min;
      
      (function animate() {
        alpha += (direction === -1) ? -1 : 1;

        if (direction === -1 && alpha < min) {
          alpha = min;
          direction = 1;
        } else if (direction === 1 && alpha > max) {
          alpha = max;
          direction = -1;
        }

        setWindowTransparency(handle, alpha);

        // Adjust the timeout delay slightly if it's too fast.
        // 10ms - 30ms is a nice range
        setTimeout(animate, 10);
      })();
    }

    (function main() {
      var HTA = document.getElementById('HTA');

      if (!HTA) return setTimeout(main, 33);

      // IE9 engine needs the title set programatically
      document.title = HTA.applicationName;

      // Load DynamicWrapperX
      dx = new ActiveXObject('DynamicWrapperX');

      // Register the APIs we need for transparency
      // This means input=window handle, long, long; return=long
      dx.Register('user32', 'SetWindowLong', 'i=hll', 'r=l');

      // input=window handle, long, long, long; return=long
      dx.Register('user32', 'SetLayeredWindowAttributes', 'i=hlll', 'r=l');

      // We'll need the FindWindow API to find our HTA's window handle
      dx.Register('user32', 'FindWindow', 'i=ss', 'r=h');

      (function getHandle() {
        // Now to use it, we need to get our HTA's window handle.
        // This will search all open windows matching this class and title
        var handle = dx.FindWindow('HTML Application Host Window Class', document.title);

        if (!handle) return setTimeout(getHandle, 33);

        moveTo(0, 0);
        resizeTo(screen.width, screen.height);

        // Now that we have the handle, set the transparency to 65%
        setWindowTransparencyKey(handle, document.body.currentStyle.backgroundColor);
      })();
    })();
  </script>
</body>
</html>
bosscube
  • 189
  • 10
  • Can you edit your answer to show a complete HTA example? So far, I've only succeeded in making it work if I have an **alert** before the **dx.FindWindow** and a button to execute **setWindowTransparency**. I want the transparency to be set when the HTA window loads, but I'm missing something. – LesFerch Nov 29 '21 at 03:02
  • @LesFerch I've updated the code to be a complete working example. The reason it worked for you with an alert is because the `FindWindow` call was running before the title was actually updated in the window titlebar. For IE9 it's even worse, as you need to programmatically set the title. The solution is just to be defensive with your code and keep trying. – bosscube Nov 30 '21 at 05:20
  • Thanks. I've updated the example again to include a simple animation loop. Have fun! – bosscube Nov 30 '21 at 13:32
  • It does not work on my Windows 10. Do I have something installed before. Please refer link. – user11714941 Dec 01 '21 at 14:24
  • @user11714941 Did you download the correct DynamicWrapperX DLL for your system (32 vs 64 bit), and did you register the DLL? You would need to put it somewhere in your PATH (or in the same folder as the HTA) and run `regsvr32 dynwrapx.dll` for example. – bosscube Dec 01 '21 at 15:26
  • I have found Dynamic Wrapper X on https://dynwrapx.script-coding.com/dwx/pages/dynwrapx.php?lang=en I downloaded and registered by Win10 Security Issue high. So next I will try to use %path% etc. – user11714941 Dec 07 '21 at 12:13
  • I have found Dynamic Wrapper X on https://dynwrapx.script-coding.com/dwx/pages/dynwrapx.php?lang=en I downloaded and tried to register but Win10 Security Issue risk "high". I tried to allow the file but it does not work. Maybe bad source? I got error "0x80040201" when I try to register. – user11714941 Dec 07 '21 at 12:57
  • I think that's a security issue - please make sure you run `regsvr32` from a command prompt with _admin priviledges_. E.g. search for "cmd" in your start menu search bar, right-click it in the results and choose Run as Administrator. – bosscube Dec 28 '21 at 21:39
  • I was wondering if there is any way to make the window background transparent, but not change the image transparency (i.e. in order to display a PNG with a transparent background over the desktop). I think the answer is no, but I just wanted to confirm that with you. – LesFerch Mar 11 '23 at 18:14
  • Hi @LesFerch, yes you can do that too. You'll just want to set a window transparency key instead of the entire window. That will effectively make all pixels of a certain color turn transparent - like a green screen. You just have to pick an obscure color that won't be used in other images/text on your app. I'll update the original answer with an example of how to do this. – bosscube Mar 12 '23 at 19:44
  • Thanks! I'm definitely interested in trying that code. – LesFerch Mar 12 '23 at 20:07
  • Ideally, I'd like to be able to display any arbitrary image with a transparent background so that it appears to be part of the desktop background image. Here's some [sample images](https://drive.google.com/drive/folders/1piEUp8B9Z2xp7ogDvgaUNJUQ-JQS2ZaM). – LesFerch Mar 13 '23 at 00:07
  • Sure, check the updated code sample @LesFerch. – bosscube Mar 13 '23 at 21:28
  • Wow, awesome sample code! Much appreciated! – LesFerch Mar 14 '23 at 01:02
  • In C# WPF, I can set WindowStyle="None", AllowsTransparency="True", Background="Transparent" and then display a PNG with transparency via an "Image" tag. This yields a much nicer result. See image comparison [here](https://drive.google.com/drive/folders/1piEUp8B9Z2xp7ogDvgaUNJUQ-JQS2ZaM). Is the same result possible in an HTA using dynwrapx? – LesFerch Mar 14 '23 at 21:08
  • @LesFerch I haven't found a way to make the result look much cleaner, except by choosing a background color that more closely matches your desktop. So in your case, maybe try #0f818c as the body background color. If that isn't sufficient, I would highly recommend getting rid of the HTA and using [Plastuer](https://plastuer.com/) instead, as this lets you use modern HTML/CSS/JS, runs in Chrome, and is built for exactly what you're doing. I use it myself for a similar reason as you, to create stock/news/traffic widgets. – bosscube Mar 15 '23 at 12:36
  • I was looking at this for adding transparency support to the slideshow mode of my app [DesktopPic](https://lesferch.github.io/DesktopPic/), but I've reached the limit of what can be achieved with an HTA (or even C# WinForms). It looks like I'll have to do a rewrite in C# WPF. Thanks for the link to Plastuer. That sounds similar to the old Active Desktop from Windows 95/98/XP days. – LesFerch Mar 15 '23 at 13:45
0

The answer is No.

This is because MSHTA is just a wrapper for the IE browser engine with reduced security to allow access to local resources etc that are not permitted through a standard internet browser.

The one thing you can do with an HTA is displaying it in fullscreen but the render is still constrained by how the HTML is rendered. Even if you adjust the background alpha using CSS it will still render with a solid white background.

The type of functionality you describe would require access to the Windows GDI which you cannot do with an HTA as it requires access to the Windows APIs.


Useful Links

user692942
  • 16,398
  • 7
  • 76
  • 175
  • I have already read https://stackoverflow.com/questions/40059020/is-there-a-way-to-set-the-alpha-channel-of-the-gui-in-a-hta-to-get-it-transparen and I want to use MICROSOFT or 3rdParty techniques to do that like anything what MS Windows already have in any lib... I don't want to create more than thounsands 1px HTAs for simple transparency. Maybe a other solution .exe would be fine. You know the Windows 7 Gadgets. They had the possibility and the web backend. I also looking for a web-desktop software that brings me the web-desktop from MS Windows 95 back to MS Windows 10 ... – user11714941 Oct 14 '21 at 08:04
  • @user11714941 might have been useful for you to mention that in your question. You can't do this with HTAs it's just not possible you need to look into using Windows GDI to manipulate the state of a window. – user692942 Oct 14 '21 at 08:26
  • Related: [Creating a transparent window in C++ Win32](https://stackoverflow.com/q/3970066) – user692942 Oct 14 '21 at 08:42