Permalink
Browse files

[Win32] Implement native menu - basics

  • Loading branch information...
1 parent e2ef58b commit a89f68f42b53f6189713f80e35a0d0434e1b5eb3 @milani milani committed Nov 2, 2012
View
@@ -341,6 +341,8 @@
'sources': [
'src/includes/util_win.cpp',
'src/native_window/native_window_win.cpp',
+ 'src/native_menu/native_menu_win.cpp',
+ 'src/native_status_icon/native_status_icon_win.cpp'
],
'defines': [
'__WIN__',
View
@@ -20,7 +20,7 @@ Persistent<Function> App::constructor;
void App::Init() {
DECLARE_CONSTRUCTOR("App");
DECLARE_PROTOTYPE_METHOD("createWindow",CreateWindow2);
- DECLARE_PROTOTYPE_METHOD("createMenu",CreateMenu);
+ DECLARE_PROTOTYPE_METHOD("createMenu",CreateMenu2);
DECLARE_PROTOTYPE_METHOD("createStatusIcon",CreateStatusIcon);
DECLARE_CLASS_FUNCTION(screenWidth, ScreenWidth);
DECLARE_CLASS_FUNCTION(screenHeight, ScreenHeight);
@@ -51,7 +51,7 @@ v8::Handle<Value> App::CreateWindow2(const Arguments& args) {
return scope.Close(Window::NewInstance(args));
}
-v8::Handle<Value> App::CreateMenu(const Arguments& args) {
+v8::Handle<Value> App::CreateMenu2(const Arguments& args) {
v8::HandleScope scope;
return scope.Close(Menu::NewInstance(args));
}
View
@@ -16,7 +16,7 @@ class App : public node::ObjectWrap {
DEFINE_CLASS_FUNCTION(ScreenWidth);
DEFINE_CLASS_FUNCTION(ScreenHeight);
DEFINE_PROTOTYPE_METHOD(CreateWindow2);
- DEFINE_PROTOTYPE_METHOD(CreateMenu);
+ DEFINE_PROTOTYPE_METHOD(CreateMenu2);
DEFINE_PROTOTYPE_METHOD(CreateStatusIcon);
static bool initialized_;
@@ -33,6 +33,9 @@ class NativeMenu {
#elif defined(__MAC__)
int AddSubMenu(NSMenu*,Settings*);
bool Attach(NSMenu*);
+#elif defined(__WIN__)
+ int AddSubMenu(HMENU&,Settings*);
+ bool Attach(HMENU&);
#endif
private:
@@ -46,6 +49,9 @@ class NativeMenu {
#elif defined(__MAC__)
NSArray* menuItems_;
#endif
+#ifdef __WIN__
+ HMENU menu_;
+#endif
};
@@ -1,5 +1,8 @@
#include <node.h>
#include <windows.h>
+#include <algorithm>
+#define min(left,right) std::min(left,right)
+#define max(left,right) std::max(left,right)
#include <gdiplus.h>
#include "appjs.h"
#include "includes/cef.h"
@@ -14,5 +17,85 @@ namespace appjs {
using namespace v8;
+void NativeMenu::Init(Settings* settings) {
+ HMENU menu = CreateMenu();
+
+ MENUINFO menuInfo;
+ memset(&menuInfo, 0, sizeof(menuInfo));
+ menuInfo.cbSize = sizeof(menuInfo);
+ menuInfo.fMask = MIM_STYLE;
+ menuInfo.dwStyle = MNS_NOTIFYBYPOS;
+ SetMenuInfo(menu,&menuInfo);
+ AddSubMenu(menu,settings);
+ menu_ = menu;
+}
+
+int NativeMenu::AddSubMenu(HMENU& menu,Settings* settings){
+ int length = settings->getInteger("length",0);
+
+ Settings* item;
+ TCHAR* label;
+ TCHAR* icon;
+ appjs_action_callback* actionCb;
+
+ for( int i = 0; i < length; i++ ) {
+
+ item = new Settings( settings->getObject( i ) );
+ label = item->getString("label",TEXT(""));
+ icon = item->getString("icon",TEXT(""));
+ actionCb = new appjs_action_callback();
+ actionCb->action = Persistent<Object>::New( item->getObject("action") );
+ actionCb->item = Persistent<Object>::New( settings->getObject( i ) );
+ actionCb->menu = this;
+
+ Settings* subsettings = new Settings(item->getObject("submenu"));
+ HMENU submenu = CreateMenu();
+ if(AddSubMenu(submenu,subsettings)) { // has submenu
+ MENUINFO menuInfo;
+ memset(&menuInfo, 0, sizeof(menuInfo));
+ menuInfo.cbSize = sizeof(menuInfo);
+ menuInfo.fMask = MIM_STYLE;
+ menuInfo.dwStyle = MNS_NOTIFYBYPOS;
+ SetMenuInfo(submenu,&menuInfo);
+ AppendMenu(menu,MF_POPUP,(UINT)submenu,label);
+ } else { // does not have submenu
+ MENUITEMINFO menuItemInfo;
+ menuItemInfo.cbSize = sizeof(MENUITEMINFO);
+ menuItemInfo.fMask = MIIM_DATA;
+ menuItemInfo.dwTypeData = label;
+ menuItemInfo.dwItemData =(ULONG_PTR) actionCb;
+
+ if( wcslen(label) == 0 ) {
+ menuItemInfo.fType = MIIM_TYPE;
+ menuItemInfo.fType = MF_SEPARATOR;
+ } else {
+ menuItemInfo.fMask |= MIIM_STRING;
+ if(item->has("icon")) {
+ menuItemInfo.fMask |= MIIM_BITMAP;
+ HBITMAP bitmap;
+ Gdiplus::Color color;
+ Gdiplus::Bitmap* img = Gdiplus::Bitmap::FromFile(icon);
+ img->GetHBITMAP(color, &bitmap);
+ menuItemInfo.hbmpItem = bitmap;
+ }
+ }
+ InsertMenuItem(menu,i,false,&menuItemInfo);
+ }
+ }
+
+ return length;
+}
+
+bool NativeMenu::Attach(HMENU& menuBar) {
+ if(!attached_) {
+ menuBar = menu_;
+ attached_ = true;
+ this->Emit("attached");
+ return true;
+ } else {
+ // already attached
+ return false;
+ }
+}
} /* appjs */
@@ -39,6 +39,8 @@ class NativeStatusIcon {
#ifdef __MAC__
NSStatusItem* statusIconHandle_;
#endif
+#ifdef __WIN__
+#endif
};
} /* appjs */
@@ -23,4 +23,12 @@ void NativeStatusIcon::Init(Settings* settings) {
}
+void NativeStatusIcon::Show(){
+ this->Emit("show");
+}
+
+void NativeStatusIcon::Hide(){
+ this->Emit("hide");
+}
+
} /* appjs */
@@ -235,23 +235,23 @@ appjs_rect NativeWindow::GetRect() {
return rect_;
}
-void NativeWindow::Emit(v8::Handle<Value>* args){
+void NativeWindow::Emit(v8::Handle<Value>* args,int length = 1){
if (!closed_) {
- node::MakeCallback(v8handle_, "emit", ARRAY_SIZE(args), args);
+ node::MakeCallback(v8handle_, "emit", length, args);
}
}
void NativeWindow::Emit(const char* event){
v8::Handle<Value> args[1] = { String::New(event) };
- Emit(args);
+ Emit(args,1);
}
void NativeWindow::Emit(const char* event, v8::Handle<Value> arg){
v8::Handle<Value> args[2] = {
String::New(event),
arg
};
- Emit(args);
+ Emit(args,2);
}
void NativeWindow::Emit(const char* event, v8::Handle<Value> arg1, v8::Handle<Value> arg2){
@@ -260,7 +260,7 @@ void NativeWindow::Emit(const char* event, v8::Handle<Value> arg1, v8::Handle<Va
arg1,
arg2
};
- Emit(args);
+ Emit(args,3);
}
void NativeWindow::Emit(const char* event, int arg1, int arg2){
@@ -269,7 +269,7 @@ void NativeWindow::Emit(const char* event, int arg1, int arg2){
Integer::New(arg1),
Integer::New(arg2)
};
- Emit(args);
+ Emit(args,3);
}
void NativeWindow::Emit(const char* event, const int arg1, const int arg2, const int arg3){
@@ -53,7 +53,7 @@ class NativeWindow {
static NativeWindow* GetWindow(CefRefPtr<CefBrowser> browser);
void SetIcon(NW_ICONSIZE size, TCHAR* path);
- void Emit(v8::Handle<v8::Value>* args);
+ void Emit(v8::Handle<v8::Value>* args,int length);
void Emit(const char* event);
void Emit(const char* event, v8::Handle<v8::Value> arg);
void Emit(const char* event, v8::Handle<v8::Value> arg1, v8::Handle<v8::Value> arg2);
@@ -475,6 +475,26 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
EndPaint(hwnd, &ps);
return 0;
}
+ case WM_MENUCOMMAND: {
+ HMENU menu = (HMENU)lParam;
+ MENUITEMINFO menuItem;
+ menuItem.cbSize = sizeof(MENUITEMINFO);
+ menuItem.fMask = MIIM_DATA;
+ int idx = wParam;
+ GetMenuItemInfo(menu,idx,TRUE,&menuItem);
+ appjs_action_callback* actionCallback = (appjs_action_callback*) menuItem.dwItemData;
+ Persistent<Object> action = actionCallback->action;
+ NativeMenu* nativeMenu = actionCallback->menu;
+
+ if(action->IsCallable()) {
+ const int argc = 1;
+ Handle<Value> argv[argc] = {actionCallback->item};
+ action->CallAsFunction(nativeMenu->GetV8Handle(),argc,argv);
+ }
+
+ nativeMenu->Emit("select",Local<Object>::New(actionCallback->item));
+ return 0;
+ }
case WM_SETFOCUS:
if (browser.get()) {
PostMessage(browser->GetWindowHandle(), WM_SETFOCUS, wParam, NULL);
@@ -566,7 +586,9 @@ int CALLBACK DirectorySelectHook(HWND hwnd, UINT msg, LPARAM lParam, LPARAM data
}
void NativeWindow::SetMenuBar(NativeMenu* nativeMenu) {
-
+ HMENU menu;
+ nativeMenu->Attach(menu);
+ SetMenu(handle_,menu);
}
void NativeWindow::OpenFileDialog(uv_work_t* req) {

0 comments on commit a89f68f

Please sign in to comment.