naqvis / webview

Crystal bindings to Webview library
MIT License
94 stars 8 forks source link

[Contribution] How to use Crystal / WebView bindings without console : #23

Open serge-hulne opened 1 year ago

serge-hulne commented 1 year ago

hide_console.cr

hide_console.cr

Source :

https://forum.crystal-lang.org/t/compilation-switch-to-avoid-the-debug-console-under-windows/5356/6

Usage:

require "../webview"
require "./hide_console"

def runApp()
    wv = Webview.window(1500, 1000, Webview::SizeHints::NONE, "Hello WebView", "http://crystal-lang.org")
    wv.run
    wv.destroy
end

runApp()

Code :

{% if flag? :windows %}
  module Crystal::System::FileDescriptor
    def self.from_stdio(fd)
      console_handle = false
      handle = LibC._get_osfhandle(fd)
      if handle != -1 && handle != -2
        handle = LibC::HANDLE.new(handle)
        # TODO: use `out old_mode` after implementing interpreter out closured var
        old_mode = uninitialized LibC::DWORD
        if LibC.GetConsoleMode(handle, pointerof(old_mode)) != 0
          console_handle = true
          if fd == 1 || fd == 2 # STDOUT or STDERR
            if LibC.SetConsoleMode(handle, old_mode | LibC::ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0
              at_exit { LibC.SetConsoleMode(handle, old_mode) }
            end
          end
        end
      end

      io = IO::FileDescriptor.new(fd, blocking: true)
      # Set sync or flush_on_newline as described in STDOUT and STDERR docs.
      # See https://crystal-lang.org/api/toplevel.html#STDERR
      if console_handle
        io.sync = true
      else
        io.flush_on_newline = true
      end
      io
    end
  end

  @[Link(ldflags: "/ENTRY:wWinMainCRTStartup")]
  @[Link(ldflags: "/SUBSYSTEM:WINDOWS")]
  lib LibCrystalMain
  end

  lib LibC
    fun CommandLineToArgvW(lpCmdLine : LPWSTR, pNumArgs : Int*) : LPWSTR*
    fun LocalFree(hMem : Void*) : Void*
  end

  fun wWinMain(
    hInstance : Void*,
    hPrevInstance : Void*,
    pCmdLine : LibC::LPWSTR,
    nCmdShow : LibC::Int
  ) : LibC::Int
    argv = LibC.CommandLineToArgvW(pCmdLine, out argc)
    wmain(argc, argv)
    ensure
      LibC.LocalFree(argv) if argv
  end
{% end %}
naqvis commented 1 year ago

Thanks @serge-hulne , but I don't think adding monkey patching to any shard is good option. Above cited issue is Crystal specific and i'm sure, future versions of Crystal will have that fixed.

serge-hulne commented 1 year ago

You could perhaps just mention it in your doc, if you want.

On Sat, Feb 18, 2023 at 3:16 PM Ali Naqvi @.***> wrote:

Thanks @serge-hulne https://github.com/serge-hulne , but I don't think adding monkey patching to any shard is good option. Above cited issue is Crystal specific and i'm sure, future versions of Crystal will have that fixed.

— Reply to this email directly, view it on GitHub https://github.com/naqvis/webview/issues/23#issuecomment-1435683578, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACKDDQ3RVHQDVXE6PPKVN3WYDKTRANCNFSM6AAAAAAU7HMYEE . You are receiving this because you were mentioned.Message ID: @.***>

lightswisp commented 1 year ago

@serge-hulne Hello there, you could try to use these methods from WinApi. (GetConsoleWindow) (ShowWindow)

Import it by:

@[Link("user32")]
lib WinApi
  fun GetConsoleWindow() : Int32*
  fun ShowWindow(handle : Int32*, ncmdshow : Int32)
end

Then invoke it like this:

handle = WinApi.GetConsoleWindow()
WinApi.ShowWindow(handle, 0)

The logic is following: get the handle via GetConsoleWindow, then pass the handle to the ShowWindow(handle, 0). Zero means, SW_HIDE.

Hope this helps!

serge-hulne commented 1 year ago

Thank you!