窗口界面接口ycwin.cpp
ycwin.cpp提供了创建窗口界面的接口,它有3种运行方式:
- 独立运行。
- 被C/C++程序调用。
- 被Javascript程序调用。
其源码如下:
……
struct ycwinCLASS
{
YHTML *phtml; //当前显示的HTML对象
YHTML *oldhtml; //待删除的HTML对象
int nTimer; //定时器
int posx,posy,width,height; //定义窗口位置和大小
byte attr;
byte esc; //是否可以用 Esc 键退出程序
virtual void _stdcall createWindow(char *htmfile=0,int htmlen=0,
int escFlag=0,int popFlag=0,
int attrFlag=0,char *srcfile=0);
virtual void _stdcall loop(); //消息循环函数
virtual int _stdcall exist();
};
……
ycwin.cpp所用头文件yc.h
ycwin.cpp源码:
#include "yc.h"
long stdcall WndProc(HWND hwnd,unsigned iMessage, unsigned wParam,long lParam)
{
YHTML *phtml = YCWIN.phtml;
switch(iMessage)
{
case WM_TIMER:
if(YCWIN.oldhtml)
{
YC_htmlFree(YCWIN.oldhtml); //释放旧页面
YCWIN.oldhtml = nullptr;
}
YCHTML->wm_timer(phtml); //处理网页的定时功能
if(YCHTML->is_stopping(phtml) && YCHTML->can_exit(phtml))
DestroyWindow(hwnd); //判断是否设置了退出标志
return FALSE;
case WM_DESTROY: //程序退出时进行销毁窗口处理
get_winattr(phtml,0); //只用于yc.exe
KillTimer(hwnd,YCWIN.nTimer); //销毁定时器
YCWIN.phtml = nullptr;
YC_htmlFree(phtml); //释放当前页面
set_ycexe_wnd(nullptr); //只用于yc.exe
PostQuitMessage(0);
return FALSE;
case WM_CLOSE:
if(YC_jsRun(phtml,L"!window.can_exit || can_exit()"))//设置退出标志
YCHTML->page_stop(phtml);
return FALSE;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if(wParam==VK_ESCAPE && !YCWIN.esc)
{
PostMessageA(hwnd,WM_CLOSE,0,0);
}
if(wParam==VK_F12 && !YCWEB->ctrlKey() && !YCWEB->shiftKey())
{
CloseWindow(hwnd);
}
else if(wParam==VK_F11 && !YCWEB->ctrlKey() && !YCWEB->shiftKey())
{
show_window();
}
else YCHTML->wm_keydown(phtml,wParam);
if(!YCWIN.attr) YCWEB->html_key_proc(phtml,wParam);
break;
case WM_CHAR:
YCHTML->wm_char(phtml,wParam);
return FALSE;
case WM_KEYUP:
YCHTML->wm_keyup(phtml,wParam);
return FALSE;
case WM_SIZE:
YCHTML->wm_size(phtml,LOWORD(lParam),HIWORD(lParam));
case WM_MOVING:
RECT rc;
if(!IsIconic(hwnd) && !get_popup(phtml))
{
int maxV = IsZoomed(hwnd); //获取窗口最大化状态
if(!maxV)
{
GetWindowRect(hwnd,&rc);
YC_jsRunf(phtml,L`localStorage.posx=%d; //保存窗口位置
localStorage.posy=%d;
localStorage.width=%d; //保存窗口大小
localStorage.height=%d`,
rc.left,rc.top,rc.right-rc.left, rc.bottom-rc.top);
}
YC_jsRunf(phtml,L"localStorage.winmax = %d",maxV);//保存最大状态
SetWindowLongA(hwnd,GWL_USERDATA,maxV); //记录窗口最大化状态
}
break;
case WM_SETFOCUS:
YCHTML->wm_setfocus(phtml);
return FALSE;
case WM_KILLFOCUS:
YCHTML->wm_killfocus(phtml);
return FALSE;
case WM_MOUSEWHEEL:
YCHTML->wm_mousewheel(phtml,wParam);
return FALSE;
case WM_MOUSEMOVE:
YCHTML->wm_mousemove(phtml,LOWORD(lParam),HIWORD(lParam));
return FALSE;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
YCHTML->wm_lbuttondown(phtml,LOWORD(lParam),HIWORD(lParam),
iMessage==WM_LBUTTONDBLCLK);
return false;
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
YCHTML->wm_rbuttondown(phtml,iMessage == WM_RBUTTONDBLCLK);
return false;
case WM_LBUTTONUP:
YCHTML->wm_lbuttonup(phtml);
return false;
case WM_RBUTTONUP:
YCHTML->wm_rbuttonup(phtml);
break;
case WM_SETCURSOR:
if(YCHTML->wm_setcursor(phtml)) return true;
break;
case WM_USER + 2002:
get_winattr(phtml,1,wParam,lParam);
return true;
case WM_ACTIVATE:
if(LOWORD(wParam) != WA_INACTIVE)
YC_jsRun(phtml,L"window.yced_OnActivate && yced_OnActivate()");
return true;
case WM_PAINT:
if(GetUpdateRect(hwnd,&rc,0) == 0) break;
PAINTSTRUCT ps;
BeginPaint(hwnd,&ps);
YIMG *pimg = YCHTML->draw_page(phtml,rc.left,rc.top,
rc.right-rc.left,rc.bottom-rc.top);
if(pimg) BitBlt(ps.hdc, rc.left,rc.top,pimg->width,
pimg->height,pimg->hdc,0,0,SRCCOPY);
EndPaint(hwnd,&ps);
return true;
}
return DefWindowProcA(hwnd,iMessage,wParam,lParam);
}
int get_popup(YHTML *phtml,bool popFlag=false)
{
if(popFlag && YC_jsRun(phtml,L"localStorage.popup == undefined"))
save_popup(phtml,1);
return YC_jsRun(phtml,L"localStorage.popup");
}
void save_popup(YHTML *phtml,int mval)
{
YC_jsRunf(phtml,L"localStorage.popup = %d",mval); //保存窗口满屏状态
}
void get_winattr(YHTML *phtml,int type,int wParam=0,int lParam=0)
{
if(!YC_jsRun(phtml,L"window.yced_getWinAttr && yced_getWinAttr()")) return;
if(type) YC_jsRunf(phtml,L"yced_mouse_hook_func(%d,%d)",wParam,lParam);
else InvalidateRect(NULL,NULL,FALSE);
}
void show_window()
{
YHTML *phtml = YCWIN.phtml;
YCWIN.posx = YC_jsRun(phtml,L"localStorage.posx"); //获取窗口位置大小
YCWIN.posy = YC_jsRun(phtml,L"localStorage.posy");
YCWIN.width = YC_jsRun(phtml,L"localStorage.width");
YCWIN.height = YC_jsRun(phtml,L"localStorage.height");
YCWEB->set_user_window_size(YCWIN.posx,YCWIN.posy,YCWIN.width,YCWIN.height);
int popV = !get_popup(phtml); //获取窗口满屏状态
save_popup(phtml,popV); //保存窗口满屏状态
int maxV = YC_jsRun(phtml,L"localStorage.winmax"); //获取窗口最大化状态
SetWindowLongA(phtml->hwnd,GWL_USERDATA,popV || maxV); //记录窗口状态
YCWEB->show_window(phtml->hwnd,YCWIN.posx,YCWIN.posy, //根据状态显示窗口
YCWIN.width,YCWIN.height,popV,maxV);
}
void set_ycexe_wnd(void *hwnd)
{
if(YCWIN.attr) YC_system(YCSYS_ycexe_wnd,hwnd,TRUE);
}
void stdcall ycwin_createWindow(YHTML *phtml,byte *obj_ptr,JSVAL *pJval,
int argnum,JSVAL *argval)
{
//实现Javascript语句: pwin.createWindow("yc.htm"...)
int htmlen = 0;
char *htmfile = null;
if(js_arg_str(0,argnum,argval)) //第0个形参argval[0]为文件名或网页名
{
htmfile = YC_wideToChar(&htmlen,argval[0].wptr,argval[0].len);
if(argnum<=1 || argval[1].type!=JS_null) htmlen = 0;
}
YCWIN.createWindow(htmfile, htmlen,
js_arg_bool(1,argnum,argval), //第1个形参
js_arg_bool(2,argnum,argval), //第2个形参
js_arg_bool(3,argnum,argval), //第3个形参
htmlen ? phtml->URLptr : null);
free(htmfile);
YCJIT->create_cppObject(phtml,pJval,&frame_data); //创建Javascript对象frame
}
void stdcall ycwin_exist(YHTML *phtml,byte *obj_ptr,JSVAL *pJval,
int argnum,JSVAL *argval)
{
//实现Javascript语句: pwin.exist()
pJval->type = JS_bool;
pJval->valBool = YCWIN.exist();
}
void stdcall frame_loop(YHTML *phtml,byte *obj_ptr,JSVAL *pJval,
int argnum,JSVAL *argval)
{
//实现Javascript语句: frame.loop()
YCWIN.loop();
}
char STR_className[256];
void ycwinCLASS::createWindow(char *htmfile,int htmlen,int escFlag,
int popFlag,int attrFlag,char *srcfile)
{
//实现c/c++语句: pwin->createWindow("yc.htm",...)
YCWIN.esc = escFlag;
YCWIN.attr = attrFlag;
lstrcpynA(STR_className,htmfile ? htmfile : "yjx",sizeof STR_className);
WNDCLASSEXA wc = {};
wc.cbSize = sizeof(wc);
wc.lpszClassName = STR_className;
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
wc.style = CS_DBLCLKS;
char exefile[MAX_PATH];
GetModuleFileNameA(NULL,exefile,MAX_PATH);
wc.hIcon = ExtractIconA(NULL,exefile,0); //从exe文件中取出图标
if(!RegisterClassExA(&wc)) return; //注册窗口
HWND hwnd = CreateWindowExA(0,STR_className,null,WS_OVERLAPPEDWINDOW,
0,0,0,0,null,null,null,null);
YPOST mPost = {};
if(htmlen)
{
mPost = { htmfile, htmlen, POST_IS_HTML };
htmfile = srcfile;
}
phtml = YC_htmlLoad(htmfile,&mPost,hwnd,
[](YHTML *phtml,unsigned iMessage,unsigned,long,void*)
{
switch(iMessage)
{
case YM_Create: //点击链接进入新页面时收到该消息
YCWIN.oldhtml = YCWIN.phtml; //保存旧页面指针
YCWIN.phtml = phtml; //设置新页面指针
break;
}
return 0;
},null,null,WEB_HISTORY);
nTimer = SetTimer(hwnd,1,10,NULL);
YC_jsRunf(phtml,L"show_window = 0x%x;",show_window); //把函数传给 yc.htm
save_popup(phtml,!get_popup(phtml,popFlag)); //窗口满屏状态取反
set_ycexe_wnd(hwnd);
show_window();
}
void ycwinCLASS::loop()
{
//实现c/c++语句: pwin->loop()
MSG msg;
while(GetMessageA(&msg, null, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
UnregisterClassA(STR_className,null);
}
int ycwinCLASS::exist()
{
//实现c/c++语句: pwin->exist()
char *cmdbuf = YCWEB->strdupA(GetCommandLineA());
if(cmdbuf)
{
char *argv[8];
int argc = YCWEB->getArgA(cmdbuf,argv,sizeof(argv)/sizeof(argv[0]));
if(argc>=3 && !strcmp(argv[2],"$$$$$$"))
{
free(cmdbuf);
YC_cppRun("yctest.cpp"); //运行内存泄漏对话框程序yctest.cpp
return 1;
}
free(cmdbuf);
}
HWND hwnd = (HWND)YC_system(YCSYS_ycexe_wnd,0,FALSE);
if(hwnd && IsWindow(hwnd)) //判断程序是否已经运行
{
int dwStyle = GetWindowLongA(hwnd,GWL_USERDATA) ?
SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
if(IsIconic(hwnd)) ShowWindow(hwnd,dwStyle);
SetForegroundWindow(hwnd); //如果程序已经运行,则将它显示在最上面
return 1;
}
return 0;
}
//定义对象pwin的方法
JS_EXT_METHOD ycwin_method[] = { { L"createWindow", ycwin_createWindow },
{ L"exist", ycwin_exist },
0,};
//定义对象frame的方法
JS_EXT_METHOD frame_method[] = { { L"loop", frame_loop },
0,};
jsDATA ycwin_data = { null, ycwin_method, L"ycwin" }; //用于创建pwin对象
jsDATA frame_data = { null, frame_method, L"frame" }; //用于创建frame对象
ycwinCLASS YCWIN;
void main(void **pObj,int isScript)
{
if((int)pObj < 1000) //当独立运行本程序时, 有argc = pObj
{
char **argv = (char**)isScript;
YCWIN.createWindow((int)pObj<=1 ? "https://www.ha123.com" : argv[1]);
YCWIN.loop();
}
else if(isScript) *pObj = &ycwin_data; //当Javascript调用本程序时
else *pObj = &YCWIN; //当C/C++调用本程序时
}
c/c++代码文件:ycwin.cpp
如果用Javascript或c/c++调用ycwin.cpp,无需编译生成ycwin.exe,系统将自动处理ycwin.cpp。
若要独立运行ycwin.cpp,则需进行下列步骤:
编译:用YC命令: ycc ycwin.cpp 生成 ycwin.exe
运行:在cmd界面执行ycwin url后,将显示url页面。