Skip to content

Instantly share code, notes, and snippets.

@khrona
Created July 19, 2012 21:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khrona/3146786 to your computer and use it in GitHub Desktop.
Save khrona/3146786 to your computer and use it in GitHub Desktop.
Quick example of how to handle popup (dropdown) menus in Awesomium 1.7 RC2 with GDI on Windows.
#include <Awesomium/WebCore.h>
#include <Awesomium/BitmapSurface.h>
#include <Awesomium/STLHelpers.h>
#include <iostream>
#define MAX_LOADSTRING 100
using namespace Awesomium;
// Global Variables:
#define WIN_WIDTH 800
#define WIN_HEIGHT 600
HINSTANCE hInst;
const wchar_t szTitle[] = L"Awesomium GDI Sample";
const wchar_t szWindowClass[] = L"AwesomiumWinClass";
WebCore* core = 0;
WebView* view;
HDC context;
HBITMAP bitmap;
unsigned char* bitmap_buf = 0;
HWND hWnd;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
std::wstring ToWideString(const WebString& str) {
std::string s = ToString(str);
return std::wstring(s.begin(), s.end());
}
void GetWindowPos(HWND hWnd, int *x, int *y)
{
HWND hWndParent = GetParent(hWnd);
POINT p = {0};
MapWindowPoints(hWnd, hWndParent, &p, 1);
(*x) = p.x;
(*y) = p.y;
}
class MenuHandler : public WebViewListener::Menu {
virtual void OnShowPopupMenu(Awesomium::WebView* caller,
const WebPopupMenuInfo& menu_info) {
// Generate the popup menu
HMENU hPopupMenu = CreatePopupMenu();
for (size_t i = 0; i < menu_info.items.size(); i++) {
const WebMenuItem& item = menu_info.items.At(i);
if (item.type == kWebMenuItemType_Option)
InsertMenu(hPopupMenu, i, MF_STRING, 1000 + i,
ToWideString(item.label).c_str());
else if (item.type == kWebMenuItemType_Group)
InsertMenu(hPopupMenu, i, MF_DISABLED | MF_STRING, 1000 + i,
ToWideString(item.label).c_str());
}
// Display the menu and get the selected ID
SetForegroundWindow(hWnd);
int winX, winY;
GetWindowPos(hWnd, &winX, &winY);
int selected_id = TrackPopupMenu(hPopupMenu, TPM_TOPALIGN |
TPM_LEFTALIGN | TPM_RETURNCMD, winX + menu_info.bounds.x,
winY + menu_info.bounds.y + 20, 0, hWnd, NULL);
// Handle the selected id
if (selected_id >= 1000)
caller->DidSelectPopupMenuItem(selected_id - 1000);
else
caller->DidCancelPopupMenu();
}
virtual void OnShowContextMenu(Awesomium::WebView *view,const Awesomium::WebContextMenuInfo &info) {
}
};
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, wchar_t*, int nCmdShow) {
WNDCLASSEX wc;
MSG msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szWindowClass;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow)) {
return FALSE;
}
WebConfig config;
core = WebCore::Initialize(config);
view = core->CreateWebView(WIN_WIDTH, WIN_HEIGHT);
view->set_menu_listener(new MenuHandler());
view->LoadURL(WebURL(WSLit("http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_optgroup")));
view->Focus();
BITMAPINFOHEADER bih = {0};
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biPlanes = 1;
bih.biWidth = WIN_WIDTH;
bih.biHeight = -(WIN_HEIGHT);
context = CreateCompatibleDC(0);
bitmap = CreateDIBSection(context, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&(bitmap_buf), 0, 0);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ReleaseDC(0, context);
DeleteObject(bitmap);
WebCore::Shutdown();
return (int) msg.wParam;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
hInst = hInstance;
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, WIN_WIDTH + 20, WIN_HEIGHT + 40,
NULL, NULL, hInstance, NULL);
// Create our WebCore Update timer, renders at a max of 66 FPS
UINT myTimer = SetTimer ( hWnd, 0, 15, NULL );
if (!hWnd) {
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hdc;
switch (message) {
case WM_COMMAND:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
case WM_TIMER: {
if (core) {
core->Update();
const BitmapSurface* surface =
static_cast<const BitmapSurface*>(view->surface());
if (surface) {
if (surface->is_dirty()) {
InvalidateRect (hWnd, NULL, FALSE);
UpdateWindow (hWnd);
}
}
}
}
break;
case WM_PAINT: {
hdc = BeginPaint(hWnd, &ps);
if (view) {
BitmapSurface* surface =
static_cast<BitmapSurface*>(view->surface());
if (surface) {
surface->CopyTo(bitmap_buf, WIN_WIDTH * 4, 4, false, false);
surface->set_is_dirty(false);
SelectObject(context, bitmap);
BitBlt(hdc, 0, 0, WIN_WIDTH, WIN_HEIGHT, context, 0, 0, SRCCOPY);
ReleaseDC(hWnd, context);
}
}
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_MOUSEMOVE: {
if (view)
view->InjectMouseMove(LOWORD(lParam), HIWORD(lParam));
break;
}
case WM_LBUTTONDOWN: {
if (view)
view->InjectMouseDown(kMouseButton_Left);
break;
}
case WM_LBUTTONUP: {
if (view)
view->InjectMouseUp(kMouseButton_Left);
break;
}
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR: {
if (view)
view->InjectKeyboardEvent(WebKeyboardEvent(message, wParam, lParam));
break;
}
case WM_QUIT:
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment