win.ui.menu无法创建图标菜单的简易分析

kio 5天前 262

查看aardio更新日志可知从v40.22.0版本开始调整了win.ui.menu库。

从该版本开始创建带有位图的的菜单时将会报错,报错信息如下图。

具体原因 win.ui.menu 库 typProc 错误的缓存时机,导致 table 类型的处理没法 更新 typProc ,手动修正即可。

修正后的效果图如下。感谢 光庆 提供的文件。

最新回复 (9)
  • zhhyit 4天前
    0 引用 2
    这个库咋用的,能给个简单的范例不
  • Mr_MAO 2天前
    0 引用 3

    菜单前加图标会更好看~~

    试试下面代码看能运行不?

    这是我以前的学习代码,当时能跑起来,现在"proc=function(){...}"报错了,所以我注释掉了

    另外,我也想知道,如何让menu前的小图标背景透明,不是那种将图标背景颜色设置为“f0f0f0”的伪透明...)

    import win.ui;
    /*DSG{{*/
    var winform = win.form(text="menu添加小图标";right=500;bottom=300)
    winform.add()
    /*}}*/
    
    import win.ui.menu; 
    
    import inet.http;
    import gdip.bitmap;
    var bmp_max = gdip.bitmap("https://pic.616pic.com/ys_bnew_img/00/28/18/krIipeSUnb.jpg")
    var bmp_min = gdip.bitmap("https://pic.616pic.com/ys_img/00/52/50/njoSx5MndS.jpg")
    
    winform.wndproc = function(hwnd,message,wParam,lParam){
        select( message ) { 
            case 0x205/*_WM_RBUTTONUP*/{
                popmenu = win.ui.popmenu(winform) 
                popmenu.add(
                   text = "最大化";
                   //proc = function(){ winform.hitMax()}; //***以前这样能加菜单点击事件,挺方便的,但现在这样用(加变量名proc)不行了
                   bitmap = bmp_max.copyHandle(16,16)   
                )
                popmenu.add(
                   text = "最小化";
                   //proc = function(){ winform.hitMin() };
                   bitmap = bmp_min.copyHandle(16,16) 
                )
                popmenu.add()  //分割线
                popmenu.add(
                    "退出(&Q)",
                    function(){ winform.close()} //***这样加菜单事件,可以√
                ) 
                popmenu.popup();
            }
        }
    }
    
    winform.show();
    win.loopMessage();



  • kio 2天前
    0 引用 4
    Mr_MAO 菜单前加图标会更好看~这是我以前的学习代码,当时能跑起来,现在"proc=function(){...}"报错了,所以我注释掉了试试下面代码行不?(另外,我也想知道 ...

    修正下menu库,代码加proc可以跑的。背景透明不太了解


  • zhhyit 2天前
    0 引用 5

    把官方的menu删了,用你的这个menu替换了,也是报错

  • kio 1天前
    0 引用 6

    这个是修改后的,上面的帖子是原版的

    //menu 菜单
    import win.ui;
    import util.metaProperty;
    namespace win.ui 
    
    getSysMenu = function(winform,revert){
    	if( revert === null ) revert = false; 
    	var hmenu = ::User32.GetSystemMenuP( winform[["hwnd"]] : winform, revert );
    	return popmenu(winform,hmenu)
    }
    
    getMenu = function( winform ){
    	var hmenu = ::User32.GetMenuP( winform[["hwnd"]] : winform  );
    	return menu(winform,hmenu)
    } 
    
    var handle2menu = { @{ _weak = "kv" } } 
    class menubase {
    
    	ctor( winform,resid,inst){
    		if( ! winform[["hwnd"]] ){
    			if(type(winform)==type.number){
    				winform = {hwnd=winform;_mapCommandProc={};}
    			}
    			else {
    				error("第一个构造参数必须指定有效窗口",3)
    			} 
    		} 
    		else {
    			winform = winform.getForm();
    		}
    		
       		this.parent = winform; 
       		if( type(resid) == type.number ){ 
       			if( type(inst) == type.string  ){
       				this.dll = ..raw.loadDll(inst);
       				inst = this.dll.gethandle();
       			}
       			this.handle = LoadMenu(inst,topointer(resid):resid); 
       			handle2menu[this.handle] = this;
       		}
       		else if( type(resid) == type.pointer ){ 
       			this.handle = resid;
       			handle2menu[this.handle] = this;
       		} 
       		
       		this._subMenus = {};
       		this._createdCommandIds = {};
       		
       		..table.gc(this,"dispose");
       	}; 
       	dispose = function(){
       		var isWindowMenu = this["(__isWindowMenu__)"];
       		if(this.handle && (!isWindowMenu) && ::User32.IsMenu(this.handle)){ 
       			DestroyMenu(this.handle);
       			this.handle = null;
       		}
       		
    		if(this.parent._freeCommandId) {
       			for(i,id in this._createdCommandIds){
       				this.parent._freeCommandId(id); 
       			}  	
       			
       			..table.clear(this._createdCommandIds)
    		}
    
    		..table.clear(this._subMenus);		
       	};
       	saveSubMenu = function(menu){
       		this._subMenus[menu] = true;
       		
       		if(this["(__isWindowMenu__)"]){
       			menu["(__isWindowMenu__)"] = true;
       			
       			for(m,v in menu._subMenus){
    				menu.saveSubMenu(m);
    			}
       		}
       	};
       	//如果在第三个参数里传入 4/*_MF_BITMAP*/ 则第一个参数必须是位图句柄(指针)
    	add = function(label,proc,flag,id){  
    		if( type(flag) == "function") flag = flag();
    		if( flag === null ) flag = 0;
        	var subMenu,bitmap,bmpUnchecked;
        	if( this.ownerDraw ) flag |= 0x100/*_MF_OWNERDRAW*/;
        	
         	if( type(label) == "table"){
         		bitmap = label.bitmap;
         		bitmapCheckd = label.bitmapCheckd; 
         		proc = label.proc ;
         		flag = label.flag : 0;
         		id = label.id;
         		subMenu = label.menu;
         		
         		label = label.text;
         	}
         	else if( type(proc)==type.table ){
         		subMenu = proc;
         		proc = null;
         	}
         			
        	if( !label ){
             	AppendMenu(this.handle,0x800/*_MF_SEPARATOR*/ | flag , 0,null );
             	return;
         	}
         	
        	if( subMenu ){
        		if( ! subMenu[["handle"]] ){
        			subMenu = ..win.ui.popmenu( this.parent ).addTable( subMenu ,2 )  
    			}  
    			elseif(subMenu.parent != this.parent ) error("子菜单与当前菜单指定了不一致的父窗体!",2);
    			
             	AppendMenu(this.handle,0x10/*_MF_POPUP*/ | flag ,tonumber(subMenu.handle),label );
             	
             	if( bitmap || bitmapCheckd){
    				this.setBitmap(tonumber(subMenu.handle),bitmap,bitmapCheckd,0x0/*_MF_BYCOMMAND*/)
    			}
    
             	this.saveSubMenu(subMenu);
             	return subMenu; 
        	}
        	else{
        	    if( (type(proc) == "number") && (id === null)){
        	    	id = proc;
        	    	proc = null;
        	    }
        	    elseif( proc === null ) proc = this[["onMenuItemClick"]];
        	    elseif( type(proc)!=type.function) { 
        			error("参数二必须是一个回调函数",2	);
        		}
        			
        		if(!id){
        			if(!this.parent@) error("父窗口不支持自动分配命令 ID",2);
        			id = this.parent._getFreeCommandId();
        			..table.push(this._createdCommandIds,id);
        		}
        		
        		if(proc !== null) this.parent._mapCommandProc[id] = proc; 
        		
        		AppendMenu(this.handle,0/*_MF_STRING*/ | flag,id ,label );
        		if( bitmap || bitmapCheckd){
                	this.setBitmap(id,bitmap,bitmapCheckd,0x0/*_MF_BYCOMMAND*/)
            	}  
        		return id;
        	}	
    	} 
    	addTable = function(args,lev){
    		if( lev === null ) lev = 1; 
    		var arg;  
    		for(i=1;#args;1){
    			arg = args[i] 
    			if(type(arg)!="table")
    				error("包含无效的菜单项参数 " + tostring(arg),lev+1)
    			
    			if(#arg){	
    				if( type(arg[2])==type.table && ( ! arg[2].handle) ){ 
    					var subMenu = ..win.ui.popmenu( this.parent ).addTable( arg[2] ,lev+1 );
    					this.saveSubMenu(subMenu);
    					
    					this.add(arg[1],subMenu,arg[3],arg[4]);
    				} 
    				else {
    					this.add(arg[1],arg[2],arg[3],arg[4]);
    				}
    			}
    			else{
    				if( arg.menu){
    					if( ! arg.menu.handle ){
    						arg.menu = ..win.ui.popmenu( this.parent ).addTable( arg.menu ,lev+1 ) 
    					}
    					this.saveSubMenu(arg.menu); 
    				} 
    				
    				this.add( arg ); 
    			}
    		} 
    		if( this.redraw ) this.redraw();
    		return this;  
    	}  
    	insert = function(position ,label,proc,flag,id){
    		if( position === null ) position = 1;
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		var subMenu,bitmap,bmpUnchecked;
    		if( this.ownerDraw ) flag |= 0x100/*_MF_OWNERDRAW*/;
    		
         	if( type(position) == "table"){
         		bitmap = position.bitmap;
         		bitmapCheckd = position.bitmapCheckd;
         		label = position.text;
         		proc = position.proc;
         		flag = position.flag : 0x400/*_MF_BYPOSITION*/;
         		id = position.id;
         		subMenu = position.menu;
         		
         		position = position.position;
         	}
         	else if( type(proc)==type.table ){
         		subMenu = proc;
         		proc = null;
         	}
         	
    		var realpos = position; 
    		if( flag&0x400==0x400 ){
    			position = position - 1; 
    		} 
    		 
    		if( !label ){
             	InsertMenu(this.handle,position,0x800/*_MF_SEPARATOR*/| flag, 0,null );
             	return;
         	}
         	 
        	if(  subMenu ){
        		if( ! subMenu[["handle"]] ){
        			subMenu = ..win.ui.popmenu( this.parent ).addTable( subMenu ,2 )  
    			}  
    			
             	InsertMenu(this.handle,position,0x10/*_MF_POPUP*/| flag,tonumber(subMenu.handle),label );
             	
             	if( bitmap || bitmapCheckd){
    				this.setBitmap(tonumber(subMenu.handle),bitmap,bitmapCheckd,0x0/*_MF_BYCOMMAND*/)
    			}
             	this.saveSubMenu(subMenu); 
        	}
        	else{
        	    
        	    if( (type(proc) == "number") && (id === null)){
        	    	id = proc;
        	    	proc = null;
        	    }
        	    elseif( proc === null ) proc = this[["onMenuItemClick"]];
        	    elseif( type(proc)!=type.function) { 
        			error("参数二必须是一个回调函数",2	);
        		}
        			
        		if(!id){
        			if(!this.parent@) error("父窗口不支持自动分配命令 ID",2);
        			id = this.parent._getFreeCommandId();
        			..table.push(this._createdCommandIds,id);
        		}
        		
        		if(proc !== null) this.parent._mapCommandProc[id] = proc; 
        	 
        		InsertMenu(this.handle,position,0/*_MF_STRING*/ | flag,id ,label );
        		
        		if( bitmap || bitmapCheckd){
                	this.setBitmap(id,bitmap,bitmapCheckd,0/*_MF_BYCOMMAND*/)
            	}    
        		return id;
        	}
    	}
    	delete = function(position,flag){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		this.reset(null,position,flag);
    		if( flag&0x400==0x400 ){ 
    			position = position - 1;  
    		}   
    		return DeleteMenu(this.handle, position, flag); 
    	}
    	remove = function(position,flag){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		this.reset(null,position,flag);
    		if( flag&0x400==0x400 ){ 
    			position = position - 1;  
    		}   
    		return RemoveMenu(this.handle, position, flag); 
    	}  
    	subMenu = function(position){
    		var h = GetSubMenu(this.handle,position-1);
    		return h ? handle2menu[h] : ..win.ui.menubase( this.parent,h );
    	} 
    	getSubMenu = function(position){
    		var h = GetSubMenu(this.handle,position);
    		return h ? handle2menu[h] : ..win.ui.menubase( this.parent,h );
    	} 
    	getId = function(position,flag){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		if( flag&0x400==0x400 ){
    			return GetMenuItemID(this.handle,position-1);
    		}  
    		return position;
    	}   
    	getPos = function(id,flag){
    		if( flag === null ) flag = 0x0/*_MF_BYCOMMAND*/;
    		if( flag&0x400==0x400 ){
    			return id;
    		}  
    		for(i=1;this.count() ){ 
    			if(this.getId(i)==id)
    				return i;	 
    		} 
    	} 
    	count = function(){
    		return GetMenuItemCount(this.handle);
    	}
    	reset = function(proc,position ,flag){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		if( position === null ) position = 1;
    		var id = this.getId(position,flag);
    		if(id && id>0){
    			if( (proc === null) && this.parent._freeCommandId) this.parent._freeCommandId(id);
    			this.parent._mapCommandProc[id] = proc;
    		}
    	}  
    	close = function(){
    		handle2menu[this.handle] = null;
    		DestroyMenu(this.handle);
    		
    		//如果是主菜单
    		if( this._onClose ){ this._onClose(); }
    		this.handle = null;
    		
    		if(this.parent && this.parent.setTimeout){
    			this.parent.setTimeout(this.dispose,100)
    		} 
    	} 
    	check = function(id,chk=true,flag){ 
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		chk = chk ? 0x8/*_MF_CHECKED*/ : 0x0/*_MF_UNCHECKED*/ 
    		CheckMenuItem(this.handle,flag&0x400==0?id:id-1,flag | chk );
    	}
    	enable = function(id,enb,flag=0x400/*_MF_BYPOSITION*/ ){ 
    		enb = ( (enb !== null)  ? ( !enb ) ) ? 0x1/*_MF_GRAYED*/  : 0;
    		EnableMenuItem(this.handle,flag&0x400==0?id:id-1,flag | enb );
    	}
    	checked = function(id ,flag){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		return ( GetMenuState(this.handle,flag&0x400==0?id:id-1, flag ) & 0x8/*_MF_CHECKED*/ ) == 0x8/*_MF_CHECKED*/
    	}
    	getString = function(id,flag ){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		var len,str = GetMenuString(this.handle,flag&0x400==0?id:id-1, 128,128,flag ) 
    		if(len)return str;
    	}
    	setString = function(id,str,flag){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		var len,str = ModifyMenuString(this.handle,flag&0x400==0?id:id-1, flag | 0x0/*_MF_STRING*/,this.getId(id,flag),str) 
    		if(len)return str;
    	};
    	setBitmap = function(position,bitmap,bmpUnchecked,flag){
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
        	if( type(bitmap) == "string") {
        		var img = ..com.picture.load(bitmap);//转化为句柄
        		bitmap = img.CopyHandle();
        	}
        	if( type(bitmapCheckd) == "string") {
        		var img = ..com.picture.load(bitmapCheckd);//转化为句柄
        		bitmapCheckd = img.CopyHandle();
        	}
        	
        	return SetMenuItemBitmaps(this.handle,this.getId(position,flag),0x111/*_WM_COMMAND*/,bitmap,bitmapCheckd);
    	};
    	click = function(position,flag){ 
    		if( flag === null ) flag = 0x400/*_MF_BYPOSITION*/;
    		::PostMessage(this.parent.hwnd, 0x111/*_WM_COMMAND*/,this.getId(position,flag) ,0);
    	} 
    	@_metaProperty;  
    }
    var menubase = menubase;
    
    namespace menubase{ 
    	var u = ::User32;
    	ModifyMenuString = u.api("ModifyMenu","int(pointer menu,int nPosition,int wFlags,int wIDNewItem,ustring lpString)")
    	GetMenuString = u.api("GetMenuString","int(pointer menu,int wIDItem,ustring& lpString,int nMaxCount,int wFlag)")
    	AppendMenu = u.api("AppendMenu","int(pointer menu,INT flags,INT newId,ustring newItem)" ) 
    	InsertMenu = u.api("InsertMenu","int(pointer menu,INT position,INT flag,INT idNew,ustring newItem)");
    	DestroyMenu  = u.api("DestroyMenu","int(pointer menu)" ) 
    	
    	GetMenuState = u.api("GetMenuState","int(pointer menu,int wID,int wFlags)")
    	CheckMenuItem = u.api("CheckMenuItem","INT(pointer menu,INT uIDCheckItem,INT uCheck)");
    	EnableMenuItem = u.api("EnableMenuItem","INT(pointer menu,INT uIDEnableItem,INT uEnable)");
    	DeleteMenu = u.api("DeleteMenu","int(pointer menu,int position,int flags)")
    	RemoveMenu = u.api( "RemoveMenu", "bool(pointer menu,INT position,INT flags)");
    	GetMenuItemID = u.api("GetMenuItemID","int(pointer menu,int nPos)")
    	
    	LoadMenu = u.api("LoadMenu","pointer(pointer hinst,ustring string)") 
    	GetSubMenu = u.api("GetSubMenu","pointer(pointer menu,int position)")
    	GetMenuItemCount = u.api("GetMenuItemCount","int(pointer menu)")
    	
    	SetMenuItemBitmaps = u.api("SetMenuItemBitmaps","bool(pointer menu,int position,int flags,pointer hBmp,pointer hBmpChecked)");
    
    	_metaProperty = ..util.metaProperty(
    		selIndex = {
    			_get = function(){
    				for(i=1; owner.count()) if(owner.checked(i)) return i;
    			}
    			_set = function( idx ){
    				var i = owner.selIndex;
    				if( i ) owner.check(i,false)
    				owner.check(idx,true)
    			} 	
    		}; 
    		selId = {
    			_get = function(){ 
    				return owner.getId(owner.selIndex);
    			}
    			_set = function( id ){
    				owner.selIndex = owner.getPos(id); 
    			} 	
    		}; 
    		selText = {
    			_get = function(){ 
    				return owner.getString(owner.selIndex);
    			}
    			_set = function( text ){
    				for(i=1;owner.count()) if(owner.getString(i) == text){
    					owner.selIndex = i;
    					break ;
    				} 
    			} 	
    		};
    		
    	)
    }
    
    menu = class{
    	ctor( winform,resid,inst )begin 
    		if(winform[["menu"]])
        		winform.menu.close(); 
        	
       		this = menubase(winform,resid,inst);//继承基类
       		
       		if(!this.handle){
       			this.handle = ::User32.CreateMenuP();
       			handle2menu[this.handle] = this;
       		}
       		
        	::User32.SetMenu(winform.hwnd,this.handle);  
        	winform.menu = this;
        	
        	this["(__isWindowMenu__)"] = true;
    	end; 
    	
    	redraw = function(){
    		::User32.DrawMenuBar(this.parent.hwnd);
    	}
    	_onClose = function(){
    		::User32.SetMenu(this.parent.hwnd,null );
    		this.parent.menu = null; //取消绑定
    		this.redraw()
    	}  
    }
    
    namespace menu{
    
    	_handle2menu = handle2menu;
    	findByHandle = function(hMenu){
    		return handle2menu[topointer(hMenu)];
    	};
    }
     
    popmenu = class{
    	
    	ctor( winform,resid,inst ) { 
       		this = menubase(winform,resid,inst);//继承基类 
       		winform = this.parent;
       		
       		if(!this.handle){
       			this.handle = CreatePopupMenu(); 
       			handle2menu[this.handle] = this;
       		}
    	}  
     
    	popup = function(x,y,screen,flag){ 
    		if( flag === null ) flag = 2/*__TPM_RIGHTBUTTON*/; 
    		//在指定坐标(x,y)弹出菜单
    		if( type(x) == type.table ) {
    			y = x.y;
    			x = x.x;
    		}
    		elseif( x===null || y===null  ){
    			var pt = ::POINT();
    			::User32.GetCursorPos(pt);
    			
    			x,y = pt.x,pt.y;
    			screen = true;
    		}
    		 
    		if( (type(x)!=type.number) || (type(y) != type.number) )
    			error("菜单弹出坐标必须是数字",2)
    		
    		var pt = ::POINT();
    		pt.x = x;
    		pt.y = y;
    		
    		if(!screen){
    			::ClientToScreen( this.parent.hwnd,pt);
    		} 
    		
    		return TrackPopupMenu( this.handle,flag ,pt.x,pt.y , 0,this.parent.hwnd,null);
    	} 
    	popId = function(x,y,screen,flag){ 
    		if( flag === null ) flag = 2/*__TPM_RIGHTBUTTON*/; 
    		return this.popup(x,y,screen,flag | 0x0100/*_TPM_RETURNCMD*/)
    	}
    	fireId = function(id,hwnd,...){ 
    		var func = id ? this.parent._mapCommandProc[id];
    		if( func ){ 
    			func(id,hwnd,...);	
    		}
    		else{ 
    			::PostMessage( hwnd[["hwnd"]] : hwnd : this.parent.hwnd, 0x111/*_WM_COMMAND*/, id,0)
    		}
    	}  
    }
    
    namespace popmenu { 
    	var u = ::User32;
    	CreatePopupMenu := u.api("CreatePopupMenu","pointer()" )
    	TrackPopupMenu := u.api("TrackPopupMenu","int(pointer menu,INT uFlags,int x,int y,int nReserved,int hWnd, pointer prcRect)" );
    }
     
    /**intellisense()
    !menu.handle = 菜单句柄
    !menu.redraw() = 重绘菜单
    !menu.add( = 添加菜单项。
    !menu.add(.() = 添加分隔线
    !menu.add(.(title,subMenu) = 添加 @subMenu 参数指定的子菜单。\n@title 参数指定菜单项文本。\n返回添加的子菜单
    !menu.add(.(title,callback,flags,commandId) = @.add("菜单标题",function(){\n	__/*指定点击菜单项的回调函数。\n参数 @flags 可选用 _MF_ 前缀的常量自定义选项。\n可选用 @commandId 参数自定义命令 ID,不指定则自动注册空闲命令 ID。\n添加菜单项以后 add 方法返回注册的菜单项命令 ID*/\n	\n})
    !menu.add(.(title,commandId) = 添加菜单项。\n参数 @title 指定菜单项文本。\n参数 @commandId 指定绑定的命令 ID,不会触发默认回调函数 onMenuItemClick 。
    !menu.add(.(menuTable) = @.add(\n	text = "标题";\n	bitmap = "位图句柄或路径、或图像数据,可选参数";\n	bitmapCheckd = "选中位图句柄或路径、或图像数据,可选参数";\n	proc = function(id){\n		__/*点击菜单项的回调函数,\n注意添加菜单项以后 add 函数返回菜单命令ID*/\n	};\n	id = 可选参数;\n	flag = 可选参数;\n);
    !menu.addTable = @.addTable( {\n	{ "菜单文本";  function(id){\n		__/*菜单事件回调函数*/\n	} }; { /*分隔线*/ }\n	{ "退出程序"; function(id){  \n		winform.close() \n 	} };\n} )
    !menu.insert( = 在指定位置插入菜单项。
    !menu.insert(.(position) = 在指定位置插入分隔线。\n@position 用数值指定位置序号。
    !menu.insert(.(position,title,subMenu) = 在指定位置插入 @subMenu 参数指定的子菜单。\n@title 参数指定菜单项文本。\n返回添加的子菜单
    !menu.insert(.(position,title,callback,flags,commandId) = @.insert(1,"菜单标题",function(){\n	__/*指定点击菜单项的回调函数。\n参数 @flags 可选用 _MF_ 前缀的常量自定义选项。\n可选用 @commandId 参数自定义命令 ID,不指定则自动注册空闲命令 ID。\n添加菜单项以后 add 方法返回注册的菜单项命令 ID*/\n	\n})
    !menu.insert(.(position,title,commandId) = 在指定位置插入菜单项。\n参数 @position 用数值指定位置序号。\n参数 @title 指定菜单项文本。\n参数 @commandId 指定绑定的命令 ID,不会触发默认回调函数 onMenuItemClick 。
    !menu.insert(.(menuTable) = @.insert(\n	position = 1;\n	text = "标题";\n	bitmap = "位图句柄或路径、或图像数据,可选参数";\n	bitmapCheckd = "选中位图句柄或路径、或图像数据,可选参数";\n	proc = function(id){\n		__/*点击菜单项的回调函数,\n注意添加菜单项以后 add 函数返回菜单命令ID*/\n	};\n	id = 可选参数;\n	flag = 可选参数;\n);
    !menu.delete( = 删除指定位置菜单项
    !menu.delete(.(菜单项序号) = 删除指定位置菜单项\n被移除的如果是子菜单则销毁,不可重用
    !menu.delete(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 移除指定命令ID的菜单项\n被移除的如果是子菜单则销毁,不可重用
    !menu.remove( = 移除指定位置菜单项
    !menu.remove(.(菜单项序号) = 移除指定位置菜单项\n被移除的如果是子菜单并不销毁,可重用
    !menu.remove(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 移除指定命令ID的菜单项\n被移除的如果是子菜单并不销毁,可重用
    !menu.getId( = 根据指定位置序号返回菜单项的命令ID
    !menu.getId(.(菜单项序号) = 根据指定位置序号返回菜单项的命令ID
    !menu.click(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 模拟点击指定命令ID的菜单项
    !menu.click(.(菜单项序号) = 模拟点击指定位置菜单项
    !menu.getPos( = 根据菜单项的命令ID返回菜单位置序号
    !menu.getPos(.(菜单项命令I) = 根据菜单项的命令ID返回菜单位置序号
    !menu.count() = 返回菜单子项数目
    !menu.subMenu(1__) = 返回指定位置子菜单
    !menu.subMenu() = !popmenu.
    !menu.reset( = 重设菜单回调函数
    !menu.reset(.(新的回调函数,菜单位置) = 重设菜单回调函数
    !menu.reset(.(新的回调函数,菜单ID,0/*_MF_BYCOMMAND*/) = 重设菜单回调函数
    !menu.close() = 关闭菜单
    !menu.check( = 勾选或取消勾选菜单项
    !menu.check(.(菜单项序号,是否选中) = 勾选或取消勾选菜单项,参数@2默认为 true
    !menu.check(.(菜单项命令ID,是否选中,0/*_MF_BYCOMMAND*/) = 勾选或取消勾选菜单项,参数@2默认为 true,\n如果参数@3为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !menu.enable( = 启用或禁用菜单项
    !menu.enable(.(菜单项序号,是否启用) = 启用或禁用菜单项,参数@2默认为 true
    !menu.enable(.(菜单项命令ID,是否启用,0/*_MF_BYCOMMAND*/) = 启用或禁用菜单项,参数@2默认为 true,\n如果参数@3为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !menu.checked( = 返回菜单项是否选中状态 
    !menu.checked(.(菜单项序号) = 返回菜单项是否选中状态 
    !menu.checked(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 返回菜单项是否选中状态e,\n如果参数@2为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !menu.getString( = 返回菜单项文本
    !menu.getString(.(菜单项序号) = 返回菜单项文本
    !menu.getString(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 返回菜单项文本,\n如果参数@2为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !menu.setString( = 设置菜单项文本
    !menu.setString(.(菜单项序号,字符串) = 设置菜单项文本
    !menu.setString(.(菜单项命令ID,字符串,0/*_MF_BYCOMMAND*/) = 设置菜单项文本,\n如果参数@3为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !menu.setBitmap( = 设置菜单项位图
    !menu.setBitmap(.(菜单项序号,位图,选中位图) = 设置菜单项位图,\n选中位图为可选参数,\n图像可以是句柄指针,也可以是图像文件路径或数据
    !menu.setBitmap(.(菜单项命令ID,位图,选中位图,0/*_MF_BYCOMMAND*/) = 设置菜单项位图,\n选中位图为可选参数,\n图像可以是句柄指针,也可以是图像文件路径或数据,\n如果参数@4为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    
    !menu.ownerDraw = 启用自绘\n系统菜单自绘没多大意义,建议使用弹出窗口模拟菜单即可
    !menu.onMenuItemClick = @.onMenuItemClick = function(id){
    	__/*默认的菜单回调函数。\n如果添加菜单项时,回调函数指定为 null 则默认调用此函数。\n如果回调函数指定为命令 ID 则不触发此默认回调。*/
    }
    !menu.selIndex = 获取或修改当前选中项索引,单选模式
    !menu.selId = 获取或修改当前选中项命令ID,单选模式
    !menu.selText = 获取或修改当前选中项文本,单选模式
    !popmenu.handle = 菜单句柄
    !popmenu.add( = 添加菜单项。
    !popmenu.add(.() = 添加分隔线
    !popmenu.add(.(title,subMenu) = 添加 @subMenu 参数指定的子菜单。\n@title 参数指定菜单项文本。\n返回添加的子菜单
    !popmenu.add(.(title,callback,flags,commandId) = @.add("菜单标题",function(){\n	__/*指定点击菜单项的回调函数。\n参数 @flags 可选用 _MF_ 前缀的常量自定义选项。\n可选用 @commandId 参数自定义命令 ID,不指定则自动注册空闲命令 ID。\n添加菜单项以后 add 方法返回注册的菜单项命令 ID*/\n	\n})
    !popmenu.add(.(title,commandId) = 添加菜单项。\n参数 @title 指定菜单项文本。\n参数 @commandId 指定绑定的命令 ID,不会触发默认回调函数 onMenuItemClick 。\n可通过 popId 方法获取用户点选找菜单项 ID。
    !popmenu.add(.(menuTable) = @.add(\n	text = "标题";\n	bitmap = "位图句柄或路径、或图像数据,可选参数";\n	bitmapCheckd = "选中位图句柄或路径、或图像数据,可选参数";\n	proc = function(id){\n		__/*点击菜单项的回调函数,\n注意添加菜单项以后 add 函数返回菜单命令ID*/\n	};\n	id = 可选参数;\n	flag = 可选参数;\n);
    !popmenu.addTable = @.addTable( {\n	{ "菜单文本";  function(id){\n		__/*菜单事件回调函数*/\n	} }; { /*分隔线*/ }\n	{ "退出程序"; function(id){  \n		winform.close() \n 	} };\n} )
    !popmenu.insert( = 在指定位置插入菜单项。
    !popmenu.insert(.(position) = 在指定位置插入分隔线。\n@position 用数值指定位置序号。
    !popmenu.insert(.(position,title,subMenu) = 在指定位置插入 @subMenu 参数指定的子菜单。\n@title 参数指定菜单项文本。\n返回添加的子菜单
    !popmenu.insert(.(position,title,callback,flags,commandId) = @.insert(1,"菜单标题",function(){\n	__/*指定点击菜单项的回调函数。\n参数 @flags 可选用 _MF_ 前缀的常量自定义选项。\n可选用 @commandId 参数自定义命令 ID,不指定则自动注册空闲命令 ID。\n添加菜单项以后 add 方法返回注册的菜单项命令 ID*/\n	\n})
    !popmenu.insert(.(position,title,commandId) = 在指定位置插入菜单项。\n参数 @position 用数值指定位置序号。\n参数 @title 指定菜单项文本。\n参数 @commandId 指定绑定的命令 ID,不会触发默认回调函数 onMenuItemClick 。
    !popmenu.insert(.(menuTable) = @.insert(\n	position = 1;\n	text = "标题";\n	bitmap = "位图句柄或路径、或图像数据,可选参数";\n	bitmapCheckd = "选中位图句柄或路径、或图像数据,可选参数";\n	proc = function(id){\n		__/*点击菜单项的回调函数,\n注意添加菜单项以后 add 函数返回菜单命令ID*/\n	};\n	id = 可选参数;\n	flag = 可选参数;\n);
    !popmenu.delete( = 删除指定位置菜单项
    !popmenu.delete(.(菜单项序号) = 删除指定位置菜单项\n被移除的如果是子菜单则销毁,不可重用
    !popmenu.delete(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 移除指定命令ID的菜单项\n被移除的如果是子菜单则销毁,不可重用
    !popmenu.remove( = 移除指定位置菜单项
    !popmenu.remove(.(菜单项序号) = 移除指定位置菜单项\n被移除的如果是子菜单并不销毁,可重用
    !popmenu.remove(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 移除指定命令ID的菜单项\n被移除的如果是子菜单并不销毁,可重用
    !popmenu.getId( = 根据指定位置序号返回菜单项的命令ID
    !popmenu.getId(.(菜单项序号) = 根据指定位置序号返回菜单项的命令ID
    !popmenu.click(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 模拟点击指定命令ID的菜单项
    !popmenu.click(.(菜单项序号) = 模拟点击指定位置菜单项
    !popmenu.getPos( = 根据菜单项的命令ID返回菜单位置序号
    !popmenu.getPos(.(菜单项命令I) = 根据菜单项的命令ID返回菜单位置序号
    !popmenu.count() = 返回菜单子项数目
    !popmenu.subMenu(1__) = 返回指定位置子菜单
    !popmenu.subMenu() = !popmenu.
    !popmenu.reset( = 重设菜单回调函数
    !popmenu.reset(.(新的回调函数,菜单位置) = 重设菜单回调函数
    !popmenu.reset(.(新的回调函数,菜单ID,0/*_MF_BYCOMMAND*/) = 重设菜单回调函数
    !popmenu.fireId(.(commandId,hwnd) = 调用 @commandId 指定的菜单项命令 ID 绑定的回调函数。\n可选指定接收命令的父窗体句柄。\n可添加任意个附加参数(转发给菜单项回调函数)。
    !popmenu.close() = 关闭菜单
    !popmenu.check( = 勾选或取消勾选菜单项
    !popmenu.check(.(菜单项序号,是否选中) = 勾选或取消勾选菜单项,参数@2默认为 true
    !popmenu.check(.(菜单项命令ID,是否选中,0/*_MF_BYCOMMAND*/) = 勾选或取消勾选菜单项,参数@2默认为 true,\n如果参数@3为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !popmenu.enable( = 启用或禁用菜单项
    !popmenu.enable(.(菜单项序号,是否启用) = 启用或禁用菜单项,参数@2默认为 true
    !popmenu.enable(.(菜单项命令ID,是否启用,0/*_MF_BYCOMMAND*/) = 启用或禁用菜单项,参数@2默认为 true,\n如果参数@3为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !popmenu.checked( = 返回菜单项是否选中状态 
    !popmenu.checked(.(菜单项序号) = 返回菜单项是否选中状态 
    !popmenu.checked(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 返回菜单项是否选中状态e,\n如果参数@2为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !popmenu.getString( = 返回菜单项文本
    !popmenu.getString(.(菜单项序号) = 返回菜单项文本
    !popmenu.getString(.(菜单项命令ID,0/*_MF_BYCOMMAND*/) = 返回菜单项文本,\n如果参数@2为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !popmenu.setString( = 设置菜单项文本
    !popmenu.setString(.(菜单项序号,字符串) = 设置菜单项文本
    !popmenu.setString(.(菜单项命令ID,字符串,0/*_MF_BYCOMMAND*/) = 设置菜单项文本,\n如果参数@3为0/*_MF_BYCOMMAND*/则参数@1为菜单命令ID
    !popmenu.setBitmap( = 设置菜单项位图
    !popmenu.setBitmap(.(菜单项序号,位图,选中位图) = 设置菜单项位图,\n选中位图为可选参数,\n图像可以是句柄指针,也可以是图像文件路径或数据
    !popmenu.setBitmap(.(菜单项命令ID,位图,选中位图,0/*_MF_BYCOMMAND*/) = 设置菜单项位图,\n选中位图为可选参数,\n图像可以是句柄指针,也可以是图像文件路径或数据,\n如果参数 @4 为 `0/*_MF_BYCOMMAND*/` 则参数 @1 为菜单命令 ID
    !popmenu.popup( = 弹出菜单并自动触发菜单项绑定的回调函数。\n成功返回 true,失败返回 false。\n\n此函数不会返回触发菜单项绑定的命令 ID,\n改用 popId 方法可返回命令 ID 而不会自动触发回调。
    !popmenu.popup(.(x坐标,y坐标,是否屏幕坐标,选项) = 弹出菜单。\n如果不指定坐标,则自动获取鼠标当前位置。\n参数 @3 指定参数 @1,@2 是否为屏幕坐标,默认为 false。\n一般不需要指定坐标参数,由函数自动设定即可。\n可选用参数 @4 指定 _TPM_ 前缀的选项,\n例如 _TPM_BOTTOMALIGN 指定坐标 y 指定菜单底部位置
    !popmenu.popId( = 弹出菜单并返回用户点选的菜单项命令 ID。\n此方法仅返回命令 ID,不会自动触发命令 ID 绑定的回调函数。\n可用返回值作为参数调用 fireId 方法触发相应的回调函数。
    !popmenu.popId(.(x坐标,y坐标,是否屏幕坐标,选项) = 弹出菜单。\n并返回用户点选菜单项的命令 ID,不会自动触发菜单项绑定的回调函数。\n未选择或发生错误则返回零。弹出菜单。\n\n如果不指定坐标,则自动获取鼠标当前位置。\n参数 @3 指定参数 @1,@2 是否为屏幕坐标,默认为 false。\n一般不需要指定坐标参数,由函数自动设定即可。\n可选用参数 @4 指定 _TPM_ 前缀的选项,\n例如 _TPM_BOTTOMALIGN 指定坐标 y 指定菜单底部位置。
    
    _TPM_CENTERALIGN=@0x4/*_TPM_CENTERALIGN*/
    _TPM_LEFTALIGN=@0/*_TPM_LEFTALIGN*/
    _TPM_RIGHTALIGN=@0x8/*_TPM_RIGHTALIGN*/
    _TPM_BOTTOMALIGN=@0x20/*_TPM_BOTTOMALIGN*/
    _TPM_TOPALIGN=@0/*_TPM_TOPALIGN*/
    _TPM_VCENTERALIGN=@0x10/*_TPM_VCENTERALIGN*/
    
    !popmenu.ownerDraw = 启用自绘\n系统菜单自绘没多大意义,建议使用弹出窗口模拟菜单即可
    !popmenu.onMenuItemClick = @.onMenuItemClick = function(id){
    	__/*默认的菜单回调函数。\n如果添加菜单项时,回调函数指定为 null 则默认调用此函数。\n如果回调函数指定为命令 ID 则不触发此默认回调。*/
    }
    !popmenu.selIndex = 获取或修改当前选中项索引,单选模式
    !popmenu.selId = 获取或修改当前选中项命令ID,单选模式
    !popmenu.selText = 获取或修改当前选中项文本,单选模式
    win.ui.menu.onMeasureItem = @.onMeasureItem = function(measureItem,dpiScaleX,dpiScaleY){ 
    	measureItem.itemWidth = 80;  
    	measureItem.itemHeight = ::GetSystemMetrics(0xF/*_SM_CYMENU*/);
    }
    win.ui.menu.onDrawItem = @.onDrawItem = function(drawItem,dpiScaleX,dpiScaleY){
    
    	return 1; 
    }
    win.ui.menu() = !menu.
    win.ui.getSysMenu()  = !popmenu.
    win.ui.popmenu() = !popmenu.
    win.ui.menu() = !menu.
    win.ui.getMenu() = !menu.
    win.ui.getMenu(hwnd) = 返回窗口菜单\n参数@1可指定窗体对象或窗体句柄\n返回的菜单对象不能添加菜单
    win.ui.getSysMenu(winform) = 返回系统菜单\n参数@1可指定窗体对象或窗体句柄\n请事先导入win.ui.menu
    win.ui.getSysMenu(winform,true) = 返回系统菜单\n并重置为缺省状态\n参数@1可指定窗体对象或窗体句柄\n请事先导入win.ui.menu
    win.ui.menu = 菜单支持库
    win.ui.menu( = 创建窗口菜单\n需要先调用 import win.ui.menu,不然发布后会报错。\n开发环境下运行,为了加快启动速度,不会百分百排除所有没有引用的库
    win.ui.menu(.(窗口) = 创建窗口菜单\n参数 @1 可指定窗口或控件对象,\n如果参数 @1 指定控件对象则自动转换为所在的父窗口对象。\n如果参数 @1 传入窗口句柄,则添加菜单项无效
    win.ui.menu(.(窗口,菜单句柄) = 使用存在的菜单句柄创建菜单对象,\n如果参数 @1 指定控件对象则自动转换为所在的父窗口对象。\n如果参数 @1 传入窗口句柄,则添加菜单项无效
    win.ui.menu._handle2menu = 句柄到菜单对象映射表
    win.ui.menu.findByHandle(.(菜单句柄) = 查找菜单对象
    win.ui.menu.findByHandle() = !menu.
    win.ui.popmenu( = 创建弹出菜单\n需要先调用 import win.ui.menu,不然发布后会报错。\n开发环境下运行,为了加快启动速度,不会百分百排除所有没有引用的库
    win.ui.popmenu(.(窗口) = 创建弹出菜单,\n如果参数 @1 指定控件对象则自动转换为所在的父窗口对象。\n如果参数 @1 传入窗口句柄,则添加菜单项无效
    win.ui.popmenu(.(窗口,菜单句柄) = 使用存在的菜单句柄创建弹出菜单对象,\n如果参数 @1 指定控件对象则自动转换为所在的父窗口对象。\n如果参数 @1 传入窗口句柄,则添加菜单项无效
    _MENU_ITEM_IS_SUBMENU = @-1/*_MENU_ITEM_IS_SUBMENU*/
    end intellisense**/


  • zhhyit 1天前
    0 引用 7
    库里var typProc = type(proc)//此处删掉 后续使用到的变量全部修改掉 typProc==修改为type(proc)== 虽然不太明白为里面的道理,但是确实可以用了,赞。 辛苦了
  • Mr_MAO 1天前
    0 引用 8

    对比了一下大佬修改的ui.menu库, 感觉不出来和原版有多大区别呀?


  • kio 1天前
    0 引用 9
    Mr_MAO 对比了一下大佬修改的ui.menu库, 感觉不出来和原版有多大区别呀?
    帖子图里面说了我说了的。具体点就是74行赋值tyProc后(整个文件有两处),table参数进分支的78行改了原始proc,但是没有更新tyProc,才导致的。
  • Mr_MAO 1天前
    0 引用 10

    明白了!你代码看的真仔细,给你点个赞   ~

返回