ห้องสมุด GUI ข้ามแพลตฟอร์มทั่วไปที่มีแกนกลางโดยใช้ Lazarus LCL
คู่มือการรวบรวม
ภาษาที่รองรับ:
ไป: https://github.com/ying32/govcl
C/C ++: เครื่องมือ/genBind/c
เครื่องกำเนิดเครื่องมือที่มีผลผูกพันภาษา: GenBind ซึ่งสร้าง C/C ++, Rust และ NIM สำหรับรายละเอียดโปรดดูไฟล์เทมเพลตที่มีผลผูกพันของภาษาเหล่านี้
ฟังก์ชั่นที่ส่งออกทั้งหมดอยู่ในรูปแบบ C มาตรฐาน ใช้การประชุม __stdcall บน Windows และแพลตฟอร์มอื่น ๆ ใช้การประชุม __cdecl
หมายเหตุ: API บางตัวที่ส่งออกโดย Liblcl ใช้วิธีการที่ดูแปลก ๆ ในขั้นต้น Liblcl ถูกเขียนขึ้นสำหรับ Govcl ดังนั้นด้วยเหตุผลบางอย่างตามธรรมชาติค่าใช้จ่ายของค่าใช้จ่ายค่อนข้างอึดอัด แต่ก็ทำอะไรไม่ถูกเช่นกัน
การเข้ารหัส utf-8 ใช้โดยค่าเริ่มต้นในทุกแพลตฟอร์ม
ไม่จำเป็นต้องมีการโทรด้วยตนเองเพื่อสร้างและปล่อย
// 定义
TApplication Application ; // 应用程序
TScreen Screen ; // 屏幕
TMouse Mouse ; // 鼠标
TClipboard Clipboard ; // 剪切板
TPrinter Printer ; // 打印机
// 获取实例类指针
Application = Application_Instance ();
Screen = Screen_Instance ();
Mouse = Mouse_Instance ();
Clipboard = Clipboard_Instance ();
Printer = Printer_Instance (); การโทรกลับเหตุการณ์แบ่งออกเป็น 3 ประเภท
รับสมาชิกแต่ละคนในอาร์เรย์พารามิเตอร์
// x86: sizeof(uintptr_t) = 4
// x64: sizeof(uintptr_t) = 8
// 从指定索引和地址获取事件中的参数
#define getParamOf ( index , ptr )
(*((uintptr_t*)((uintptr_t)ptr + (uintptr_t)index*sizeof(uintptr_t))))
typedef void ( * ESYSCALL0 )();
typedef void ( * ESYSCALL1 )( intptr_t );
typedef void ( * ESYSCALL2 )( intptr_t , uintptr_t );
typedef void ( * ESYSCALL3 )( intptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL4 )( intptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL5 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL6 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL7 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL8 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL9 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL10 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL11 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
typedef void ( * ESYSCALL12 )( intptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t , uintptr_t );
// 回调函数原型
// f: 通过SetOnXXX传入的Id或者函数指针
// args: 参数组数指针,通过getParamOf来获取每个成员
// argcount: 参数数组长度
// 事件回调
static void * LCLAPI doEventCallbackProc ( void * f , void * args , long argCount ) {
// 获取参数的宏
#define _A_ ( index )
getParamOf(index, args)
switch ( argCount ) {
case 0 : (( ESYSCALL0 ) ( f ))(); break ;
case 1 : (( ESYSCALL1 ) ( f ))( _A_ ( 0 )); break ;
case 2 : (( ESYSCALL2 ) ( f ))( _A_ ( 0 ), _A_ ( 1 )); break ;
case 3 : (( ESYSCALL3 ) ( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 )); break ;
case 4 : (( ESYSCALL4 ) ( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 2 )); break ;
case 5 : (( ESYSCALL5 ) ( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 )); break ;
case 6 : (( ESYSCALL6 ) ( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 ), _A_ ( 5 )); break ;
case 7 : (( ESYSCALL7 ) ( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 ), _A_ ( 5 ), _A_ ( 6 )); break ;
case 8 : (( ESYSCALL8 ) ( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 ), _A_ ( 5 ), _A_ ( 6 ), _A_ ( 7 )); break ;
case 9 : (( ESYSCALL9 ) ( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 ), _A_ ( 5 ), _A_ ( 6 ), _A_ ( 7 ), _A_ ( 8 )); break ;
case 10 : (( ESYSCALL10 )( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 ), _A_ ( 5 ), _A_ ( 6 ), _A_ ( 7 ), _A_ ( 8 ), _A_ ( 9 )); break ;
case 11 : (( ESYSCALL11 )( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 ), _A_ ( 5 ), _A_ ( 6 ), _A_ ( 7 ), _A_ ( 8 ), _A_ ( 9 ), _A_ ( 10 )); break ;
case 12 : (( ESYSCALL12 )( f ))( _A_ ( 0 ), _A_ ( 1 ), _A_ ( 2 ), _A_ ( 3 ), _A_ ( 4 ), _A_ ( 5 ), _A_ ( 6 ), _A_ ( 7 ), _A_ ( 8 ), _A_ ( 9 ), _A_ ( 10 ), _A_ ( 11 )); break ;
}
return NULL ;
}
// 设置回调
SetEventCallback ( GET_CALLBACK ( doEventCallbackProc )); // f: addr
// msg: TMessage
void * LCLAPI doMessageCallbackProc ( void * f , void * msg ) {
(( void ( * )( void * )) f )( msg );
return NULL ;
}
// 设置回调
SetMessageCallback ( GET_CALLBACK ( doMessageCallbackProc )); static TThreadProc threadSyncProc ;
void * LCLAPI doThreadSyncCallbackProc () {
if ( threadSyncProc ) {
(( TThreadProc ) threadSyncProc )();
threadSyncProc = NULL ;
}
return NULL ;
}
// 设置回调
SetThreadSyncCallback ( GET_CALLBACK ( doThreadSyncCallbackProc ));
// 线程同步操作
void ThreadSync ( TThreadProc fn ) {
#ifdef __GNUC__
pthread_mutex_lock ( & threadSyncMutex );
#else
EnterCriticalSection ( & threadSyncMutex );
#endif
threadSyncProc = fn ;
Synchronize (FALSE);
threadSyncProc = NULL ;
#ifdef __GNUC__
pthread_mutex_unlock ( & threadSyncMutex );
#else
LeaveCriticalSection ( & threadSyncMutex );
#endif
} // 集合加法,val...中存储为位的索引,下标为0
TSet Include ( TSet s , uint8_t val ) {
return ( TSet )( s | ( 1 << val ));
}
// 集合减法,val...中存储为位的索引,下标为0
TSet Exclude ( TSet s , uint8_t val ) {
return ( TSet )( s & (~( 1 << val )));
}
// 集合类型的判断,val表示位数,下标为0
BOOL InSet ( uint32_t s , uint8_t val ) {
if (( s & ( 1 << val )) != 0 ) {
return TRUE;
}
return FALSE;
} #define GET_CALLBACK ( name )
(void*)&name
static void init_lib_lcl () {
#ifdef __GNUC__
pthread_mutex_init ( & threadSyncMutex , NULL );
#else
InitializeCriticalSection ( & threadSyncMutex );
#endif
// 设置事件的回调函数
SetEventCallback ( GET_CALLBACK ( doEventCallbackProc ));
// 设置消息回调
SetMessageCallback ( GET_CALLBACK ( doMessageCallbackProc ));
// 设置线程同步回调
SetThreadSyncCallback ( GET_CALLBACK ( doThreadSyncCallbackProc ));
// 初始实例类
Application = Application_Instance ();
Screen = Screen_Instance ();
Mouse = Mouse_Instance ();
Clipboard = Clipboard_Instance ();
Printer = Printer_Instance ();
}
static void un_init_lib_lcl () {
#ifdef __GNUC__
pthread_mutex_destroy ( & threadSyncMutex );
#else
DeleteCriticalSection ( & threadSyncMutex );
#endif
} #include "liblcl.h"
#ifdef _WIN32
// UTF8解码
char * UTF8Decode ( char * str ) {
int len = MultiByteToWideChar ( CP_UTF8 , 0 , str , -1 , 0 , 0 );
wchar_t * wCharBuffer = ( wchar_t * ) malloc ( len * sizeof ( wchar_t ) + 1 );
MultiByteToWideChar ( CP_UTF8 , 0 , str , -1 , wCharBuffer , len );
len = WideCharToMultiByte ( CP_ACP , 0 , wCharBuffer , -1 , 0 , 0 , 0 , NULL );
char * aCharBuffer = ( char * ) malloc ( len * sizeof ( char ) + 1 );
WideCharToMultiByte ( CP_ACP , 0 , wCharBuffer , -1 , aCharBuffer , len , 0 , NULL );
free (( void * ) wCharBuffer );
return aCharBuffer ;
}
#endif
// 按钮单击事件
void onButton1Click ( TObject sender ) {
ShowMessage ( "Hello world!" );
}
// 文件拖放事件
void onOnDropFiles ( TObject sender , void * aFileNames , intptr_t len ) {
printf ( "aFileNames: %p, len=%dn" , aFileNames , len );
intptr_t i ;
// GetFPStringArrayMember 为一个从Lazarus的string数组中获取成员的函数。
for ( i = 0 ; i < len ; i ++ ) {
#ifdef _WIN32
// 由于liblcl使用的是UTF-8编码,所以获取或者传入的在Windows下都要经过UTF-8编/解码
char * filename = UTF8Decode ( GetFPStringArrayMember ( aFileNames , i ));
#else
// Linux与macOS默认都是UTF-8,则无需编/解码
char * filename = GetFPStringArrayMember ( aFileNames , i );
#endif
printf ( "file[%d]=%sn" , i + 1 , filename );
#ifdef _WIN32
free (( void * ) filename );
#endif
}
}
// 窗口键盘按下事件
void onFormKeyDown ( TObject sender , Char * key , TShiftState shift ) {
printf ( "key=%d, shift=%dn" , * key , shift );
if ( * key == vkReturn ) {
ShowMessage ( "press Enter!" );
}
TShiftState s = Include ( 0 , ssAlt );
if ( InSet ( s , ssAlt )) {
printf ( "ssAlt1n" );
}
s = Exclude ( s , ssAlt );
if (! InSet ( s , ssAlt )) {
printf ( "ssAlt2n" );
}
}
// 编辑框内容改变事件
void onEditChange ( TObject sender ) {
printf ( "%sn" , Edit_GetText ( sender ));
}
int main ()
{
// 加载库
#ifdef _WIN32
if ( load_liblcl ( "liblcl.dll" )) {
#endif
#ifdef __linux__
if ( load_liblcl ( "liblcl.so" )) {
#endif
#ifdef __APPLE__
if ( load_liblcl ( "liblcl.dylib" )) {
#endif
// 主窗口显示在任务栏,仅Windows有效
Application_SetMainFormOnTaskBar ( Application , TRUE);
// 应用程序标题,影响到:比如ShowMessage的标题。
Application_SetTitle ( Application , "Hello LCL" );
// 初始化应用程序
Application_Initialize ( Application );
// 创建窗口
TForm form = Application_CreateForm ( Application , FALSE);
// 设置窗口标题
Form_SetCaption ( form , "LCL Form" );
// 设置窗口位置
Form_SetPosition ( form , poScreenCenter );
// --- 拖放文件测试 ---
// 接受文件拖放
Form_SetAllowDropFiles ( form , TRUE);
// 拖放文件事件
Form_SetOnDropFiles ( form , onOnDropFiles );
// 窗口优先接受按键,不受其它影响
Form_SetKeyPreview ( form , TRUE);
// 窗口按键事件
Form_SetOnKeyDown ( form , onFormKeyDown );
// ---------- 从内存流或者文件加载UI布局文件 ----------
// 从文件加载窗口设置
// 从流加载
//TMemoryStream mem = NewMemoryStream();
//MemoryStream_Write(mem, data, datalen);
//MemoryStream_SetPosition(mem, 0);
//ResFormLoadFromStream(mem, form);
//MemoryStream_Free(mem);
// 从文件加载
//ResFormLoadFromFile("./Form1.gfm", form);
// ---------- 动态创建控件 ----------
// 创建一个按钮
TButton btn = Button_Create ( form );
// 设置子父窗口
Button_SetParent ( btn , form );
// 设置按钮单击事件
Button_SetOnClick ( btn , onButton1Click );
// 设置按钮标题
Button_SetCaption ( btn , "button1" );
// 设置按钮在Parent的左边位置
Button_SetLeft ( btn , 100 );
// 设置按钮在Parent的顶边位置
Button_SetTop ( btn , 100 );
// 创建一个单行文件框(多行为TMemo)
TEdit edit = Edit_Create ( form );
// 设置子父窗口
Edit_SetParent ( edit , form );
// 设置左边
Edit_SetLeft ( edit , 10 );
// 设置顶边
Edit_SetTop ( edit , 10 );
// 设置编辑器内容改变事件
Edit_SetOnChange ( edit , onEditChange );
// 运行app
Application_Run ( Application );
// 释放liblcl库
close_liblcl ();
}
return 0 ;
}รักษาข้อตกลงการอนุมัติเช่นเดียวกับส่วนประกอบ Lazarus LCL: การคัดลอก. modifiedlgpl