Skip to content

Instantly share code, notes, and snippets.

@pravic
Last active December 11, 2019 19:42
Show Gist options
  • Save pravic/c9a18fae3493f00dc6be3bf0009ee50c to your computer and use it in GitHub Desktop.
Save pravic/c9a18fae3493f00dc6be3bf0009ee50c to your computer and use it in GitHub Desktop.
sciter.lite plain-win
<html window-icon="https://sciter.com/wp-content/themes/sciter/!images/favicon.ico">
<head>
<title>Minimalistic Sciter demo</title>
<style>
html {
background: radial-gradient(75% 75%, circle farthest-side, white, orange, rgb(0,0,204));
color: #fff;
}
html:rtl {
mapping: left-to-right(background);
}
a { color: white; }
code { font-weight: bold; }
</style>
<script type="text/tiscript">
// view.caption = $(head > title).value;
view.caption = "dummy caption";
stdout.println("init script");
$(#machine).text = Sciter.machineName();
$(#version).text = String.printf("%d.%d.%d.%d",
(Sciter.VERSION >> 16) & 0xffff, Sciter.VERSION & 0xffff,
(Sciter.REVISION >> 16) & 0xffff, Sciter.REVISION & 0xffff);
try {
// since 4.2.5.0
$(#revision).text = Sciter.BUILD.toString();
} catch(e) {
$(#revision).text = "N/A";
}
var counter = 0;
$(button#append).on("click", function(){
stdout.println("on_append");
$(body).$append(<h1#test>{++counter }</h1>);
});
$(button#open).on("click", function(){
var fn = view.selectFile(#open,
"HTML Files (*.htm,*.html)|*.HTM;*.HTML|All Files (*.*)|*.*" , "html" );
stdout.println("selected file: " + fn);
$(body).$append(<h1#test>{fn}</h1>);
});
// Some tricks with hyperlinks:
$(a).on("click", function() {
Sciter.launch(this.attributes["href"]);
return true;
});
for (var a in $$(a)) {
a.attributes["title"] = a.attributes["href"];
}
stdout.println("document is ready");
</script>
</head>
<body>
<h1>Minimal Sciter Application</h1>
<p>Running on <em #machine /> machine</p>
<p>Sciter version <span #version /> rev <span #revision /></p>
<button #append>Append</button>
<button #open>Open</button>
<select>
<option>Some</option>
<option>Items</option>
<option>in select</option>
</select>
<section class=footer>
<p>You can inspect this window in the <a href="https://sciter.com/developers/development-tools/">Inspector tool</a>
from the <a href="https://sciter.com/download/">Sciter SDK</a>.</p>
<p>Run the Inspector first and then press <code>CTRL+SHIFT+I</code> in this window.</p>
</section>
</body>
</html>
#include "stdafx.h"
#include "plain-win.h"
HINSTANCE ghInstance = 0;
#define WINDOW_CLASS_NAME L"sciter-plain-window" // the main window class name
bool window::init_class()
{
static ATOM cls = 0;
if (cls)
return true;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = wnd_proc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = ghInstance;
wcex.hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_PLAINWIN));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = 0;//MAKEINTRESOURCE(IDC_PLAINWIN);
wcex.lpszClassName = WINDOW_CLASS_NAME;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
cls = RegisterClassEx(&wcex);
return cls != 0;
}
LRESULT window::handle_notification(LPSCITER_CALLBACK_NOTIFICATION pnm)
{
switch (pnm->code)
{
case SC_INVALIDATE_RECT:
this->redraw_window();
return 0;
}
return __super::handle_notification(pnm);
}
LRESULT window::on_load_data(LPSCN_LOAD_DATA nm)
{
sciter::debug_output::instance()->printf("%ws\n", nm->uri);
return __super::on_load_data(nm);
}
bool window::handle_scripting_call(HELEMENT he, SCRIPTING_METHOD_PARAMS& params)
{
sciter::debug_output::instance()->printf("he %p call '%s'\n", he, params.name);
return __super::handle_scripting_call(he, params);
}
window::window()
: hwnd()
, loaded()
, memDc()
, memBm()
, memSize()
, mouseEnter()
{
init_class();
hwnd = CreateWindow(WINDOW_CLASS_NAME, L"demo", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 1024, 768, NULL, NULL, ghInstance, this);
SetWindowLongPtr(hwnd, GWLP_USERDATA, LONG_PTR(this));
if (!hwnd)
return;
init();
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
}
window* window::ptr(HWND hwnd)
{
return reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
bool window::init()
{
auto version = SAPI()->version;
// create an engine instance
auto ok = SciterProcX(get_hwnd(), SCITER_X_MSG_CREATE(GFX_LAYER_SKIA, FALSE));
// setup callbacks
SciterSetOption(get_hwnd(), SCITER_SET_DEBUG_MODE, true);
this->setup_callback();
sciter::debug_output::instance()->printf("initialized\n");
// load file
{
wchar_t buf[260];
GetModuleFileNameW(NULL, buf, _countof(buf));
PathRemoveFileSpecW(buf);
#pragma comment(lib, "shlwapi.lib")
std::wstring path = buf;
path += L"\\";
path += L"minimal.htm";
ok = this->load_file(path.c_str());
this->loaded = true;
SetWindowTextA(this->hwnd, "Loaded");
sciter::debug_output::instance()->printf("loaded\n");
sciter::attach_dom_event_handler(get_hwnd(), this);
}
return true;
}
void window::redraw_window()
{
::RedrawWindow(this->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
}
LRESULT CALLBACK window::wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
window* self = ptr(hWnd);
switch (message)
{
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_MOUSEMOVE:
case WM_MOUSELEAVE:
{
unsigned mb = 0;
if (wParam & MK_LBUTTON)
mb |= MOUSE_BUTTONS::MAIN_MOUSE_BUTTON;
if (wParam & MK_RBUTTON)
mb |= MOUSE_BUTTONS::PROP_MOUSE_BUTTON;
if (wParam & MK_MBUTTON)
mb |= MOUSE_BUTTONS::MIDDLE_MOUSE_BUTTON;
unsigned ks = 0;
if (wParam & MK_SHIFT)
ks |= KEYBOARD_STATES::SHIFT_KEY_PRESSED;
if (wParam & MK_CONTROL)
ks |= KEYBOARD_STATES::CONTROL_KEY_PRESSED;
if (wParam & MK_ALT)
ks |= KEYBOARD_STATES::ALT_KEY_PRESSED;
MOUSE_EVENTS evt = MOUSE_EVENTS::MOUSE_MOVE;
switch (message)
{
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
evt = MOUSE_EVENTS::MOUSE_DOWN;
break;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
evt = MOUSE_EVENTS::MOUSE_UP;
break;
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
evt = MOUSE_EVENTS::MOUSE_DCLICK;
break;
case WM_MOUSEMOVE:
evt = MOUSE_EVENTS::MOUSE_MOVE;
if (!self->mouseEnter) {
evt = MOUSE_EVENTS::MOUSE_ENTER;
TRACKMOUSEEVENT me = { sizeof(TRACKMOUSEEVENT) };
me.dwFlags = TME_LEAVE;
me.hwndTrack = hWnd;
TrackMouseEvent(&me);
self->mouseEnter = true;
}
break;
case WM_MOUSELEAVE:
evt = MOUSE_EVENTS::MOUSE_LEAVE;
self->mouseEnter = false;
break;
}
POINT pos = { LOWORD(lParam), HIWORD(lParam) };
auto ok = SciterProcX(self, SCITER_X_MSG_MOUSE(evt, MOUSE_BUTTONS(mb), KEYBOARD_STATES(ks), pos));
if (!ok)
ok = 0;
break;
}
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
{
unsigned ks = 0;
if (GetKeyState(VK_CONTROL) < 0)
ks |= KEYBOARD_STATES::CONTROL_KEY_PRESSED;
if (GetKeyState(VK_SHIFT) < 0)
ks |= KEYBOARD_STATES::SHIFT_KEY_PRESSED;
if (GetKeyState(VK_MENU))
ks |= KEYBOARD_STATES::ALT_KEY_PRESSED;
KEY_EVENTS evt;
switch (message)
{
case WM_KEYDOWN: evt = KEY_EVENTS::KEY_DOWN; break;
case WM_KEYUP: evt = KEY_EVENTS::KEY_UP; break;
case WM_CHAR: evt = KEY_EVENTS::KEY_CHAR; break;
}
unsigned code = translate_key(wParam);
auto ok = SciterProcX(self, SCITER_X_MSG_KEY(evt, code, KEYBOARD_STATES(ks)));
if (!ok)
ok = 0;
break;
}
case WM_DESTROY:
{
SciterProcX(self, SCITER_X_MSG_DESTROY());
PostQuitMessage(0);
break;
}
case WM_SIZE:
{
auto width = LOWORD(lParam);
auto height = HIWORD(lParam);
auto ok = SciterProcX(self, SCITER_X_MSG_SIZE(width, height));
break;
}
case WM_SETFOCUS:
case WM_KILLFOCUS:
{
auto ok = SciterProcX(self, SCITER_X_MSG_FOCUS(message == WM_SETFOCUS));
if (!ok)
ok = 0;
self->redraw_window();
break;
}
case WM_ERASEBKGND:
{
return 1;
}
case WM_PAINT:
{
if (!self->loaded)
break;
auto on_bitmap = [](LPCBYTE rgba, INT x, INT y, UINT width, UINT height, LPVOID param)
{
auto* self = reinterpret_cast<window*>(param);
PAINTSTRUCT ps = {};
if (HDC dc = BeginPaint(self->hwnd, &ps)) {
if (!self->memDc || self->memSize.cx != width || self->memSize.cy != height) {
if (self->memBm)
DeleteObject(self->memBm);
self->memDc = CreateCompatibleDC(dc);
self->memBm = CreateCompatibleBitmap(dc, width, height);
}
auto oldBm = SelectObject(self->memDc, self->memBm);
// Sciter: pointer to BGRA bitmap
// GDI: each DWORD represents blue, green, and red for a pixel.
// The value for blue is in the least significant 8 bits,
// followed by 8 bits each for green and red
BITMAPINFO bmi = {};
auto& info = bmi.bmiHeader;
info.biSize = sizeof(BITMAPINFOHEADER);
info.biWidth = width;
info.biHeight = -int(height);
info.biPlanes = 1;
info.biBitCount = 32;
info.biCompression = BI_RGB;
auto rcWidth = ps.rcPaint.right - ps.rcPaint.left;
auto rcHeight = ps.rcPaint.bottom - ps.rcPaint.top;
auto ok = StretchDIBits(self->memDc, 0, 0, width, height, 0, 0, width, height, rgba, &bmi, DIB_RGB_COLORS, SRCCOPY);
BitBlt(dc, x, y, width, height, self->memDc, 0, 0, SRCCOPY);
SelectObject(self->memDc, oldBm);
EndPaint(self->hwnd, &ps);
}
};
SCITER_X_MSG_PAINT paint;
paint.targetType = SPT_RECEIVER;
paint.target.receiver.param = self;
paint.target.receiver.callback = on_bitmap;
auto ok = SciterProcX(self, paint);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// the WinMain
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
ghInstance = hInstance;
SciterSetOption(NULL, SCITER_SET_SCRIPT_RUNTIME_FEATURES,
ALLOW_FILE_IO |
ALLOW_SOCKET_IO |
ALLOW_EVAL |
ALLOW_SYSINFO);
SciterSetOption(NULL, SCITER_SET_DEBUG_MODE, true);
SciterSetOption(NULL, SCITER_SET_UX_THEMING, true);
// Perform application initialization:
OleInitialize(NULL); // for shell interaction: drag-n-drop, etc.
auto* cls = SciterClassName();
sciter::debug_output _dbg;
window wnd;
if (!wnd.is_valid())
return FALSE;
// Main message loop:
for (;;) {
SciterProcX(wnd.get_hwnd(), SCITER_X_MSG_HEARTBIT(GetTickCount()));
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message == WM_QUIT)
break;
Sleep(1000 / 60);
}
OleUninitialize();
return 0;
}
#include "sciter-x-lite-keycodes.h"
unsigned window::translate_key(unsigned vk)
{
auto in_range = [vk](unsigned vk_start, unsigned vk_end, unsigned kb_first) -> unsigned
{
if (vk >= vk_start && vk <= vk_end)
return (vk - vk_start) + kb_first;
return 0;
};
if (auto kb = in_range('0', '9', KB_0))
return kb;
if (auto kb = in_range('A', 'Z', KB_A))
return kb;
if (auto kb = in_range(VK_NUMPAD0, VK_NUMPAD9, KB_NUMPAD0))
return kb;
if (auto kb = in_range(VK_F1, VK_F24, KB_F1))
return kb;
switch (vk)
{
case VK_ESCAPE: return KB_ESCAPE;
case VK_BACK: return KB_BACK;
case VK_TAB: return KB_TAB;
case VK_SPACE: return KB_SPACE;
case VK_SHIFT: return KB_SHIFT;
case VK_CONTROL:return KB_CONTROL;
case VK_MENU: return KB_MENU;
}
return 0;
}
#pragma once
#include "resource.h"
#include "sciter-x.h"
#include "sciter-x-host-callback.h"
#include "sciter-x-request.hpp"
#include "sciter-x-dom.hpp"
#include "sciter-x-behavior.h"
#include "../../demos.lite/sciter-glfw-opengl/aux-fs.h"
extern HINSTANCE ghInstance;
class window :
public sciter::host<window>,
public sciter::event_handler
{
HWND hwnd;
bool loaded;
bool mouseEnter;
HDC memDc;
HBITMAP memBm;
SIZE memSize;
public:
// notification_handler traits:
HWINDOW get_hwnd() const { return (HWINDOW)this; }
HINSTANCE get_resource_instance() const { return ghInstance; }
LRESULT handle_notification(LPSCITER_CALLBACK_NOTIFICATION pnm);
virtual LRESULT on_load_data(LPSCN_LOAD_DATA pnmld) override;
virtual bool handle_scripting_call(HELEMENT he, SCRIPTING_METHOD_PARAMS& params) override;
/* sciter::request / LOAD_MYSELF testing */
/*LRESULT on_load_data(LPSCN_LOAD_DATA pnmld) {
aux::wchars wu = aux::chars_of(pnmld->uri);
if(wu == const_wchars("res:go.png"))
{
LPCBYTE pb = 0; UINT cb = 0;
load_resource_data(wu.start+4, pb, cb);
sciter::request rq( pnmld->requestId );
rq.succeeded(200,pb,cb);
return LOAD_MYSELF;
}
return sciter::host<window>::on_load_data(pnmld);
}*/
window();
bool is_valid() const { return hwnd != 0; }
protected:
static LRESULT CALLBACK wnd_proc(HWND, UINT, WPARAM, LPARAM);
static window* ptr(HWND hwnd);
static bool init_class();
bool init(); // instance
void redraw_window();
static unsigned translate_key(unsigned vk);
};
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN
#define WINDOWLESS
// Windows Header Files:
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include "sciter-x.h"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment