PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » PureBasic для Windows » Расширенный буфер обмена


Расширенный буфер обмена

Сообщений 1 страница 9 из 9

1

Нашёл пример в код-архиве реагирующий на изменение буфера обмена, решил попробовать соединить с SQLite в плане сохранения в базу данных с большой историей до 1000 и более или по дате за неделю и более, чтобы всегда можно было найти то, что когда-то копировал.

Проба (Linux)
1. База данных имеет проблемы с экранированием вставляемого текста, так как скобки и кавычки являются элементами кода.
2. Сохранение окна, из которого произошло копирование тоже пока не получилось.

Код:
; Файл:     Clipboard_OwnerChange.pb
; Функционал:        калбак при смене владельца буфера обмена - Linux
; Автор:          Omi (оригинального примера)
; Дата:            Май. 28, 2016
; Компилятор: PureBasic 5.22/5.31/5.4x
; ОС:       Linux: (X/K/L)ubuntu, Mint, 32/64, Ascii/Uni
;--------------------------------------------------------------

EnableExplicit

ImportC ""
	gdk_screen_get_window_stack(*screen.GdkScreen)
	gdk_x11_window_get_xid(*window)
	gtk_window_get_title(*window);
	gdk_atom_intern(atom_name.p-utf8, only_if_exists)
	
	gtk_widget_get_window(*widget.GtkWidget)
	g_signal_connect(*instance, detailed_signal.p-utf8, *c_handler, *pdata, destroy= 0, flags= 0) As "g_signal_connect_data"
EndImport

Enumeration GdkEventType
	#GDK_OWNER_CHANGE  = 34; 2.6+
	#GDK_GRAB_BROKEN   = 35; 2.8+
	#GDK_DAMAGE        = 36; 2.14+
	#GDK_TOUCH_BEGIN   = 37; 3.4+
	#GDK_TOUCH_UPDATE  = 38; 3.4+
	#GDK_TOUCH_END     = 39; 3.4+
	#GDK_TOUCH_CANCEL  = 40; 3.4+
	#GDK_TOUCHPAD_SWIPE= 41; 3.18+
	#GDK_TOUCHPAD_PINCH= 42; 3.18+
	#GDK_EVENT_LAST    = 43; 2.18+
EndEnumeration

Enumeration GdkOwnerChange
	#GDK_OWNER_CHANGE_NEW_OWNER
	#GDK_OWNER_CHANGE_DESTROY
	#GDK_OWNER_CHANGE_CLOSE
EndEnumeration

Structure GdkEventOwnerChange
	type.i;l
	*window.GdkWindow
	send_event.b
	CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    PB_Alignment1.b[3]
	CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
    PB_Alignment1.b[7]
	CompilerEndIf
	*owner.GdkWindow
	reason.i
	selection.i
	time.l
	selection_time.l
EndStructure

; Object constants
#Win_Main  = 0
#btn  = 0
#sql  = 0

; #ClipboardTimer= 999

Global.i gEvent
; Global.i gTime= 1000
Global   gClipboard= gtk_clipboard_get_(gdk_atom_intern("CLIPBOARD", #True))

; === мой контент ===

UseSQLiteDatabase()
Declare ForceDirectories(Dir.s)
Declare Screen_GetWindowStack(id)
Declare.s GetWinTitle(id)

Global sqlite$, sqliteTrue = 0

sqlite$ = GetPathPart(ProgramFilename()) + GetFilePart(ProgramFilename(), #PB_FileSystem_NoExtension) + ".sqlite"
If FileSize(sqlite$) < 0
	; 	Если рядом с прогой файла нет, то прога не портабельная и ищем файл-базы в папках конфигов
	; 	Создаём в AppData\Roaming, если в текущей не удалось
	sqlite$ = GetHomeDirectory() + ".config/ClipboardSQLite/ClipboardSQLite.sqlite"
	If FileSize(sqlite$) > -1
    sqliteTrue = 1
	ElseIf ForceDirectories(GetPathPart(sqlite$)) And CreateFile(0, sqlite$)
    CloseFile(0)
    sqliteTrue = 1
	EndIf
EndIf

; MessageRequester("",  Str(sqliteTrue) + Str(OpenDatabase(#sql, sqlite$, "", "")))
; End

Define tmp$

Global sqlTbDate$ = "data"
Global sqlTbWinID$ = "WinID"
Global sqlTbText$ = "Text"
; база: Дата добавления | текст данных | окно? с которого взято
If sqliteTrue And OpenDatabase(#sql, sqlite$, "", "")
	; 	если не добавили таблицу то завершаем программу
	If Not DatabaseUpdate(#sql, "CREATE TABLE IF NOT EXISTS '" + "txt" + "' (" + sqlTbDate$ + " int, '" + sqlTbWinID$ + "' Text, '" + sqlTbText$ + "' Text);")
    MessageRequester("", "Не удалось добавить таблицу в базу данных")
    End
	EndIf
Else
	MessageRequester("", "Не удалось создать базу данных")
	End
EndIf

; IsDatabase(#Database)

ProcedureC Callback_Clipboard_OwnerChange(*clipboard, *event.GdkEventAny, user_data)
	Protected *eventownerchange.GdkEventOwnerChange
	Static t = 0
; 	Protected   *window, gpointer
	
	If *event\type = #GDK_OWNER_CHANGE
;     If t
;     	t - 1
;     	ProcedureReturn
;     EndIf
;     t+1
    	*eventownerchange= *event
	;     gdk_window_get_user_data_(*eventownerchange\window, @gpointer)
	;     If gpointer
	;     	Debug PeekS(gtk_window_get_title_(gpointer), -1, #PB_UTF8)
	;     EndIf
	;     Debug PeekS(gtk_window_get_title(*eventownerchange\window), -1, #PB_UTF8)
	;     Debug gtk_window_get_title(*eventownerchange\window)
    	
    	If Not DatabaseUpdate(#sql, "BEGIN TRANSACTION;INSERT INTO '" + "txt" + "' (" + sqlTbDate$ + "," + sqlTbWinID$ + "," + sqlTbText$ + ") values ('" + Str(Date()) + "','" + GetWinTitle(*eventownerchange\window) + "','" + GetClipboardText() + "');COMMIT;")
        ; 	    	MessageRequester("", "Не удалось добавить элемент")
        RunProgram("zenity", "--info --title=Ошибка --text=Не_удалось_добавить_элемент", "")
    	EndIf
	EndIf
EndProcedure

Procedure Create_WinMain()
	If OpenWindow(#Win_Main, 300, 200, 500, 200, "Слежка за буфером обмена", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    
    TextGadget  (#PB_Any, 5,  5, 490, 26, "Перенести части в буфер обмена и с другими программами")
    ButtonGadget(#btn, 5, 40, 300, 26, "Показать данные")
    
    g_signal_connect(gClipboard, "owner-change", @Callback_Clipboard_OwnerChange(), 0)
	EndIf
EndProcedure

Create_WinMain()

Repeat
	gEvent= WaitWindowEvent()
	
	Select gEvent
    	
    Case #PB_Event_Gadget
    	Select EventGadget()
        Case #btn
        	;             SetClipboardText("Тестовый текст PureBasic!")
        	
        	
        	If DatabaseQuery(#sql, "SELECT * FROM txt") ; Получите все записи в таблице 'txt'
            tmp$ = ""
            While NextDatabaseRow(#sql) ; Цикл для каждой записи
            	tmp$ + FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", Val(GetDatabaseString(#sql, 0))) + #TAB$ + GetDatabaseString(#sql, 1) + #TAB$ + GetDatabaseString(#sql, 2) + #CRLF$ ; Отображение содержимого первого поля
            Wend
            
            FinishDatabaseQuery(#sql)
        	EndIf
        	MessageRequester("", tmp$)
        	
    	EndSelect
    	
    Case #PB_Event_CloseWindow
    	CloseDatabase(#sql)
    	End
    	
	EndSelect
ForEver

;==================================================================
;
; Author:    ts-soft     
; Date:       March 5th, 2010
; Explain:
;     modified version from IBSoftware (CodeArchiv)
;     on vista and above check the Request for "User mode" or "Administrator mode" in compileroptions
;    (no virtualisation!)
;==================================================================
Procedure ForceDirectories(Dir.s)
	Static tmpDir.s, Init, delim$
	Protected result
	CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
    	delim$ = "\"
    CompilerCase #PB_OS_Linux
    	delim$ = "/"
	CompilerEndSelect
	
	If Len(Dir) = 0
    ProcedureReturn #False
	Else
    If Not Init
    	tmpDir = Dir
    	Init   = #True
    EndIf
    If (Right(Dir, 1) = delim$)
    	Dir = Left(Dir, Len(Dir) - 1)
    EndIf
    If (Len(Dir) < 3) Or FileSize(Dir) = -2 Or GetPathPart(Dir) = Dir
    	If FileSize(tmpDir) = -2
        result = #True
    	EndIf
    	tmpDir = ""
    	Init = #False
    	ProcedureReturn result
    EndIf
    ForceDirectories(GetPathPart(Dir))
    ProcedureReturn CreateDirectory(Dir)
	EndIf
EndProcedure


Procedure.s GetWinTitle(id)
	Protected ProgOutput.s, Pos, Pos2, ProgrammId
	
	id = Screen_GetWindowStack(id)
	ProgrammId = RunProgram("wmctrl", "-l", "", #PB_Program_Open | #PB_Program_Read)
	
	If ProgrammId
    While ProgramRunning(ProgrammId)
    	If AvailableProgramOutput(ProgrammId)
        ProgOutput + ReadProgramString(ProgrammId) + #LF$
    	EndIf
    Wend
    CloseProgram(ProgrammId)
    
    ProgOutput = ReplaceString(ProgOutput, "  ", #TAB$)
;     Pos = FindString(ProgOutput, "0x" + Hex(id))
    Pos = FindString(ProgOutput, Hex(id))
    If Pos
    	Pos2 = FindString(ProgOutput, #LF$, Pos)
;     	Debug "Найдено 1 " + Hex(id)
    	If Pos2
;         Debug "Найдено 2"
        ProgOutput = StringField(Mid(ProgOutput, Pos, Pos2 - Pos), 2, #TAB$)
        Pos = FindString(ProgOutput, " ", 3)
        If Pos
        	ProgOutput = Mid(ProgOutput, Pos + 1)
        EndIf
    	EndIf
    Else
    	ProgOutput = Str(id)
;     	Debug "Не найдено"
    EndIf
;     Debug "0x" + Hex(id)
;     Debug "ProgOutput" +ProgOutput
    If ProgOutput = ""
    	ProgOutput = "none"
    EndIf
    ProcedureReturn ProgOutput
	Else
    Debug "wmctrl must be installed !!!"
    Debug "install: sudo apt-get install wmctrl"
	EndIf
EndProcedure



Procedure Screen_GetWindowStack(id)
	Protected   *gList0.GList  = gdk_screen_get_window_stack(gdk_display_get_default_screen_(gdk_display_get_default_()))
	Protected   *gList.GList   = *gList0
	Protected   *window, *decorations
	Protected.i xid
	
	If *gList
    Repeat
    	*window= *glist\data
;     	Debug Str(*window - 800) + " = " + Str(id)
    	If *window - 800 = id
        xid= gdk_x11_window_get_xid(*window)
        Break
    	EndIf
    	*gList= *gList\next
    	g_object_unref_(*window)
    Until *gList = 0
	EndIf
	g_list_free_(*gList0);      free list
	ProcedureReturn xid
EndProcedure

0

2

Вариант 2 упрощённый. Без SQL. Проблема: не понятно как вызвать вывод меню горячей клавишей. Есть идея разделить на 2 исполняемых файла, один следит за буфером и наполняет, второй (маленький) показывает меню. Запуск исполняемого файла по горячей клавише можно задать в оболочке DE. Вопрос, как взаимодействовать программам между собой. Например программа должна найти окно по заголовку и получить от неё дескриптор на список.

Код:
EnableExplicit

ImportC ""
	gdk_atom_intern(atom_name.p-utf8, only_if_exists)
	g_signal_connect(*instance, detailed_signal.p-utf8, *c_handler, *pdata, destroy= 0, flags= 0) As "g_signal_connect_data"
EndImport

Enumeration GdkEventType
	#GDK_OWNER_CHANGE  = 34; 2.6+
	#GDK_GRAB_BROKEN   = 35; 2.8+
	#GDK_DAMAGE        = 36; 2.14+
	#GDK_TOUCH_BEGIN   = 37; 3.4+
	#GDK_TOUCH_UPDATE  = 38; 3.4+
	#GDK_TOUCH_END     = 39; 3.4+
	#GDK_TOUCH_CANCEL  = 40; 3.4+
	#GDK_TOUCHPAD_SWIPE= 41; 3.18+
	#GDK_TOUCHPAD_PINCH= 42; 3.18+
	#GDK_EVENT_LAST    = 43; 2.18+
EndEnumeration

Enumeration GdkOwnerChange
	#GDK_OWNER_CHANGE_NEW_OWNER
	#GDK_OWNER_CHANGE_DESTROY
	#GDK_OWNER_CHANGE_CLOSE
EndEnumeration

Structure GdkEventOwnerChange
	type.i;l
	*window.GdkWindow
	send_event.b
	CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    PB_Alignment1.b[3]
	CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
    PB_Alignment1.b[7]
	CompilerEndIf
	*owner.GdkWindow
	reason.i
	selection.i
	time.l
	selection_time.l
EndStructure

; Object constants
#Win_Main  = 0
#btn  = 0
#Menu  = 0

; #ClipboardTimer= 999

Global.i gEvent
; Global.i gTime= 1000
Global   gClipboard= gtk_clipboard_get_(gdk_atom_intern("CLIPBOARD", #True))

; === мой контент ===

Declare ForceDirectories(Dir.s)
Declare Screen_GetWindowStack(id)
Declare.s GetWinTitle(id)

Global NewList FavList.s()
Global i


Define tmp$, EM


ProcedureC Callback_Clipboard_OwnerChange(*clipboard, *event.GdkEventAny, user_data)
	Protected *eventownerchange.GdkEventOwnerChange
	Static t = 0
; 	Protected   *window, gpointer
	
	If *event\type = #GDK_OWNER_CHANGE
;     If t
;     	t - 1
;     	ProcedureReturn
;     EndIf
;     t+1
    	*eventownerchange= *event
    	If AddElement(FavList())
        FavList() = GetClipboardText()
    	EndIf
    
	EndIf
EndProcedure

If OpenWindow(#Win_Main, 300, 200, 500, 200, "Слежка за буфером обмена", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	
	ButtonGadget(#btn, 5, 40, 300, 26, "Показать данные")
	
	g_signal_connect(gClipboard, "owner-change", @Callback_Clipboard_OwnerChange(), 0)
	
	Repeat
    gEvent= WaitWindowEvent()
    
    Select gEvent
        
    	Case #PB_Event_Gadget
        Select EventGadget()
        	Case #btn
            If CreatePopupMenu(#Menu)
            	i=0
            	ForEach FavList()
                MenuItem(i, FavList())
                i+1
            	Next
            	i-1
            EndIf
            DisplayPopupMenu(#Menu, WindowID(#Win_Main))
            
        EndSelect
            
    	Case #PB_Event_Menu        ; кликнут элемент всплывающего Меню
        
        EM = EventMenu()
        Select EM
        	Case 0 To i
            tmp$ = GetMenuItemText(#Menu, EM)
            MessageRequester("", tmp$)
        EndSelect
    	Case #PB_Event_CloseWindow
        End
        
    EndSelect
	ForEver
EndIf

Нашёл рабочий пример

Отредактировано AZJIO (22.05.2021 20:13:31)

0

3

AZJIO написал(а):

Есть идея разделить на 2 исполняемых файла, один следит за буфером и наполняет, второй (маленький) показывает меню.

Смысл?

AZJIO написал(а):

Вопрос, как взаимодействовать программам между собой.

Проще всего сделать чтобы одна программа запустила сервер, а вторая подключалась к нему.

0

4

Пётр
На официальном форуме задал вопрос, может у кого будут идеи, чтобы получить всё в одном файле.
А пример с сервером есть? Я помню этот вопрос подымался на предыдущем форуме.

Я соединил 2 кода в один, но у меня подозрение что X11 и окна это вроде как разные подсистемы, и может поэтому не работают. Хотя логически объединяя код я понимал, что каждая вещь работает сама по себе, несмотря что это внутри одного кода. То есть окно создаётся и хоткей забиндил, единственное я поместил обработчик событий в один цикл и GUI-шниый работает с задержкой, а  хоткей неизвестно, может быть в этом причина. Ну в общем я отладчик вставил в калбак и он не реагирует на копирование, а значит цикл пока не причём.

Отредактировано AZJIO (22.05.2021 21:36:27)

0

5

ещё немного экспериментов и ListSize(FavList()) возвращает огромное число при отсутствии добавления элементов. Какая то несовместимость с ProcedureC. Вынес добавление в отдельную процедуру Procedure, но при формировании меню проблема остаётся. Цикл событий закомментировал, теперь он вроде не должен влиять. Но Callback также не работает.

Код:
; Converted from cheshirekow's C-Code:
; http://lists.freedesktop.org/archives/xorg/2010-October/051373.html
;http://www.purebasic.fr/english/viewtopic.php?f=15&t=49107&hilit=global+shortcut

EnableExplicit

#ShiftMask = 1
#ControlMask = 4
#AltMask = 8
#WinMask = 64

#GrabModeAsync = 1
#KeyPress = 2
#KeyPressMask = 1

; http://book.itep.ru/10/keys.htm
#XK_C = $0043
#XK_K = $004B
#XK_N = $004E

; Debug #PB_Key_K
; Debug #XK_K

; ShiftMask   |     1 | Shift
; LockMask    |     2 | Caps LOCK
; ControlMask |     4 | Ctrl
; Mod1Mask    |     8 | Alt
; Mod2Mask    |    16 | Num LOCK
; Mod3Mask    |    32 | Scroll LOCK
; Mod4Mask    |    64 | Windows
; Mod5Mask    |   128 | ???

ImportC "-lX11"
	XCloseDisplay(*Display)
	XDefaultRootWindow(*Display)
	XGrabKey(*Display, KeyCode.I, Modifiers.I, GrabWindow.I, OwnerEvents.i, PointerMode.I, KeyboardMode.I)
	XKeysymToKeycode(*Display, KeySym.I)
	XNextEvent(*Display, *XEvent)
	XOpenDisplay(*Display)
	XSelectInput(*Display, Window.I, EventMask.I)
	XUngrabKey(*Display, KeyCode.I, Modifiers.I, GrabWindow.I)
EndImport

ImportC "-lxcb" : EndImport
ImportC "-lXau" : EndImport
ImportC "-lXdmcp" : EndImport

Structure XEvent
	EventType.I
	SendEvent.I
	*Display
	EventWindow.I
	RootWindow.I
	ChildWindow.I
	Time.I
	x.I
	y.I
	x_root.I
	y_root.I
	Mask.I
	KeyCode.I
	SameScreen.I
EndStructure

Define *Display
Define Event.XEvent
Define KeyCode.I
Define RootWindow.I


; из примера реакции на буфер обмена
; =======================================
ImportC ""
	gdk_atom_intern(atom_name.p-utf8, only_if_exists)
	g_signal_connect(*instance, detailed_signal.p-utf8, *c_handler, *pdata, destroy= 0, flags= 0) As "g_signal_connect_data"
EndImport

Enumeration GdkEventType
	#GDK_OWNER_CHANGE  = 34; 2.6+
	#GDK_GRAB_BROKEN   = 35; 2.8+
	#GDK_DAMAGE        = 36; 2.14+
	#GDK_TOUCH_BEGIN   = 37; 3.4+
	#GDK_TOUCH_UPDATE  = 38; 3.4+
	#GDK_TOUCH_END     = 39; 3.4+
	#GDK_TOUCH_CANCEL  = 40; 3.4+
	#GDK_TOUCHPAD_SWIPE= 41; 3.18+
	#GDK_TOUCHPAD_PINCH= 42; 3.18+
	#GDK_EVENT_LAST    = 43; 2.18+
EndEnumeration

Enumeration GdkOwnerChange
	#GDK_OWNER_CHANGE_NEW_OWNER
	#GDK_OWNER_CHANGE_DESTROY
	#GDK_OWNER_CHANGE_CLOSE
EndEnumeration

Structure GdkEventOwnerChange
	type.i;l
	*window.GdkWindow
	send_event.b
	CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    PB_Alignment1.b[3]
	CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
    PB_Alignment1.b[7]
	CompilerEndIf
	*owner.GdkWindow
	reason.i
	selection.i
	time.l
	selection_time.l
EndStructure

#Win_Main  = 0
#btn  = 0
#Menu  = 0

Global gEvent
Global   gClipboard= gtk_clipboard_get_(gdk_atom_intern("CLIPBOARD", #True))

; === мой контент ===

; Declare ForceDirectories(Dir.s)
; Declare Screen_GetWindowStack(id)
; Declare.s GetWinTitle(id)

Global NewList FavList.s()
Global i

Define tmp$, EM

Procedure Added()
    If AddElement(FavList())
    	FavList() = GetClipboardText()
    EndIf
	ProcedureReturn 0
EndProcedure

ProcedureC Callback_Clipboard_OwnerChange(*clipboard, *event.GdkEventAny, user_data)
	Protected *eventownerchange.GdkEventOwnerChange

	Debug "Callback"
	If *event\type = #GDK_OWNER_CHANGE
    *eventownerchange= *event
    Added()
	EndIf
EndProcedure

Procedure DispMenu()
	If CreatePopupMenu(#Menu)
    i=0
    Debug ListSize(FavList())
    If ListSize(FavList()) < 20
    	ForEach FavList()
        MenuItem(i, FavList())
        i+1
    	Next
    Else
    	MessageRequester("","ошибка")
    EndIf
    i-1
	EndIf
	DisplayPopupMenu(#Menu, WindowID(#Win_Main))
	ProcedureReturn 0
EndProcedure

If OpenWindow(#Win_Main, 300, 200, 500, 200, "Слежка за буфером обмена", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	g_signal_connect(gClipboard, "owner-change", @Callback_Clipboard_OwnerChange(), 0)
EndIf
; =======================================

*Display = XOpenDisplay(0)

If *Display
	RootWindow = XDefaultRootWindow(*Display)
	
	If RootWindow
    KeyCode = XKeysymToKeycode(*Display, #XK_K)
    XGrabKey(*Display, KeyCode, #AltMask, RootWindow, #False, #GrabModeAsync, #GrabModeAsync)
    XSelectInput(*Display, RootWindow, #KeyPressMask)
    
    Repeat
    	XNextEvent(*Display, @Event)
    	Debug Event\EventType
    	If Event\EventType = #KeyPress
        DispMenu()
;         DisplayPopupMenu(#Menu, *Display)
        ;         MessageRequester("Info", "Global Hotkey <Ctrl> + <Shift> + <K> detected and removed!")
        ;             пока разрегистрируем клавишу
        XUngrabKey(*Display, KeyCode, #AltMask, RootWindow)
        Break
    	EndIf
    	
    	
;     	Select WaitWindowEvent()
;         	
;         Case #PB_Event_Menu        ; кликнут элемент всплывающего Меню
;         	
;         	EM = EventMenu()
;         	Select EM
;             Case 0 To i
;             	tmp$ = GetMenuItemText(#Menu, EM)
;             	MessageRequester("", tmp$)
;         	EndSelect
;         Case #PB_Event_CloseWindow
;         	End
;     	EndSelect
    	
    ForEver
    
    XCloseDisplay(*Display)
	EndIf
EndIf

убрал 3 строки и Callback сработал хотя бы на выходе.

Код:
ImportC "-lxcb" : EndImport
ImportC "-lXau" : EndImport
ImportC "-lXdmcp" : EndImport

Как я не подумал чтобы отправить гуи с её циклом в другой поток.
С потоками прокол, функции OpenWindow, WaitWindowEvent, WindowEvent могут быть вызваны только из главного потока.

Отредактировано AZJIO (23.05.2021 13:55:27)

0

6

AZJIO написал(а):

А пример с сервером есть?

В справке есть https://www.purebasic.com/documentation … er.pb.html
https://www.purebasic.com/documentation … nt.pb.html

0

7

Пётр
Это вызовет законную, как бы мягче сказать истерику. Тут просто выкладываешь прогу на Linux-форумах, уже косо смотрят, типа нет возможности скомпилировать исходник, ссылку на офсайт проги начинают рассматривать под микроскопом, а если  в исходнике будет упоминание сервер-клиент не в плане обмена между прогами, а в плане сетевого интерфейса, и с учётом что прога следит да буфером обмена, то это уже за гранью.

В худшем случае можно сервером сохранить указатель в файл, а клиентом прочитать. Указатель то постоянный, в момент запуска сервера запишет 1 раз. А клиент на каждом вызове будет его читать.

Отредактировано AZJIO (23.05.2021 15:46:55)

0

8

Сервер (через файл)

Код:
EnableExplicit

ImportC ""
	gdk_atom_intern(atom_name.p-utf8, only_if_exists)
	g_signal_connect(*instance, detailed_signal.p-utf8, *c_handler, *pdata, destroy= 0, flags= 0) As "g_signal_connect_data"
EndImport

Enumeration GdkEventType
	#GDK_OWNER_CHANGE  = 34; 2.6+
	#GDK_GRAB_BROKEN   = 35; 2.8+
	#GDK_DAMAGE        = 36; 2.14+
	#GDK_TOUCH_BEGIN   = 37; 3.4+
	#GDK_TOUCH_UPDATE  = 38; 3.4+
	#GDK_TOUCH_END     = 39; 3.4+
	#GDK_TOUCH_CANCEL  = 40; 3.4+
	#GDK_TOUCHPAD_SWIPE= 41; 3.18+
	#GDK_TOUCHPAD_PINCH= 42; 3.18+
	#GDK_EVENT_LAST    = 43; 2.18+
EndEnumeration

Enumeration GdkOwnerChange
	#GDK_OWNER_CHANGE_NEW_OWNER
	#GDK_OWNER_CHANGE_DESTROY
	#GDK_OWNER_CHANGE_CLOSE
EndEnumeration

Structure GdkEventOwnerChange
	type.i;l
	*window.GdkWindow
	send_event.b
	CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    PB_Alignment1.b[3]
	CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
    PB_Alignment1.b[7]
	CompilerEndIf
	*owner.GdkWindow
	reason.i
	selection.i
	time.l
	selection_time.l
EndStructure

Structure Flist
	List FavList.s()
EndStructure

; Object constants
#Win_Main  = 0
#btn  = 0
#Menu  = 0


Global.i gEvent
Global   gClipboard= gtk_clipboard_get_(gdk_atom_intern("CLIPBOARD", #True))

; === мой контент ===

Declare ForceDirectories(Dir.s)
Declare Screen_GetWindowStack(id)
Declare.s GetWinTitle(id)

; Global NewList FavList.s()
Global FavList.Flist
Global i


Define tmp$, EM


; tmp$ = GetPathPart(ProgramFilename()) + GetFilePart(ProgramFilename(), #PB_FileSystem_NoExtension) + ".cfg"
tmp$ = GetPathPart(ProgramFilename()) + "fuf.cfg"
If FileSize(tmp$) < 0
	If CreateFile(0, tmp$)
;      WriteInteger(0, PeekI(FavList()))
    WriteInteger(0, FavList)
    Debug FavList
    CloseFile(0)
	EndIf
Else
	If OpenFile(0, tmp$)
     WriteInteger(0, FavList)
    Debug FavList
    CloseFile(0)
	EndIf
EndIf

ProcedureC Callback_Clipboard_OwnerChange(*clipboard, *event.GdkEventAny, user_data)
	Protected *eventownerchange.GdkEventOwnerChange
	Static t = 0
	
	If *event\type = #GDK_OWNER_CHANGE
;     If t
;     	t - 1
;     	ProcedureReturn
;     EndIf
;     t+1
    	*eventownerchange= *event
    	If AddElement(FavList\FavList())
        FavList\FavList() = GetClipboardText()
    	EndIf
    
	EndIf
EndProcedure

If OpenWindow(#Win_Main, 300, 200, 500, 200, "Слежка за буфером обмена", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	
	ButtonGadget(#btn, 5, 40, 300, 26, "Показать данные")
	
	g_signal_connect(gClipboard, "owner-change", @Callback_Clipboard_OwnerChange(), 0)
	
	Repeat
    gEvent= WaitWindowEvent()
    
    Select gEvent
        
    	Case #PB_Event_Gadget
        Select EventGadget()
        	Case #btn
            If CreatePopupMenu(#Menu)
            	i=0
            	ForEach FavList\FavList()
                MenuItem(i, FavList\FavList())
                i+1
            	Next
            	i-1
            EndIf
            DisplayPopupMenu(#Menu, WindowID(#Win_Main))
            
        EndSelect
            
    	Case #PB_Event_Menu        ; кликнут элемент всплывающего Меню
        
        EM = EventMenu()
        Select EM
        	Case 0 To i
            tmp$ = GetMenuItemText(#Menu, EM)
            MessageRequester("", tmp$)
        EndSelect
    	Case #PB_Event_CloseWindow
        End
        
    EndSelect
	ForEver
EndIf

клиент

Код:
EnableExplicit

Structure Flist
	List FavList.s()
EndStructure

Define *i, tmp$

; Procedure Exe(*FavList.Flist)
Procedure Exe(*i.Flist)
	Protected *FavList.Flist = *i
    	ForEach *FavList\FavList()
        Debug *FavList\FavList()
    	Next
EndProcedure

tmp$ = GetPathPart(ProgramFilename()) + "fuf.cfg"
If FileSize(tmp$) < 0
	MessageRequester("","файла нет")
Else
	If OpenFile(0, tmp$)
    *i = ReadInteger(0)
    Debug *i
     CloseFile(0)
     Exe(*i)
	EndIf
EndIf

но толку пока нет. Debug нормально возвращает указатель списка в сервере и клиенте (один и тот же), проблем нет, но вот использовать список по указателю почему то пока не может.

Ой, надо переделать, в примерах структуры инициализация списка по-другому.

Отредактировано AZJIO (23.05.2021 17:09:01)

0

9

Ещё попытка, скачать cl-manager

Прога только для Linux, описание в комплекте. Вызов меню из трея. Падала при 10-минутной работе забыв что прога была запущена, хотя логически я не видел ошибок в коде, всё вроде как понятно и очевидно.

Добавил в архив виндовый вариант EXE.

Отредактировано AZJIO (03.08.2021 18:20:27)

0


Вы здесь » PureBasic - форум » PureBasic для Windows » Расширенный буфер обмена