Разработка приложений на языках C-C++ с использованием Tcl-Tk

в 17:06, , рубрики: C, c++, development, GUI, open source, pkcs7, sap, tcl/tk, Графические оболочки, интерфейсы, Программирование, сертификат

image Мощный функционал скриптового языка Tcl в сочетании с виджетами Tk/TTK позволяет создавать в этой среде серьезные приложения. Этому способствует также его кросплатформенность и прекрасная интеграция с языками программирования C/C++.
И в качестве примера сразу приведем пример программы на языке C. Эта программа строит графический интерфейс, имеющий поле для ввода строки, кнопку, при нажатии которой вычисляется длина строки, и поля для отображения результата:

image

Текст программы на языке C выглядит следующим образом:

#include <stdlib.h>
#include <stdio.h>
#include <tcl.h>
#include <tk.h>
#include <string.h>
Tcl_Interp * tcl_interp ;
int lenStr(){
    int code;
    int len;
    char slen[256];
    char *res;
/*Читаем из widget-а введенную строку в переменную tcl с именем a*/
    code = Tcl_Eval(tcl_interp, "set a [.ent1 get];");
/*Присваиваем значение tcl-переменной a строке res в нашем коде:*/
    res = (char *)Tcl_GetVar(tcl_interp, "a", TCL_APPEND_VALUE);
/*Вычисляем средствами языка C длину прочитанной строки:*/
    len = strlen(res);
/*Переводим длину в строку*/
    slen[0] = '';
    sprintf(slen, "%i", len);
/*Теперь полученное значение slen присваиваем Tcl-переменной  lens:*/
    Tcl_SetVar(tcl_interp, "lens", slen, TCL_GLOBAL_ONLY);
/*Чистим виджет, в который будет записана длина введенной строки*/
    code = Tcl_Eval(tcl_interp, ".ent4 delete 0 end;");
/*И в чистый виджет вставляем полученное значене*/
    code = Tcl_Eval(tcl_interp, ".ent4 insert 0 $lens;");
/*И возвращаемся*/
    return TCL_OK;
}
int main (int argc, char *argv[]) {
/*Tcl/Tk - скрипт нашего примера  */
    char strtcl[] ="
	wm title . "Пример программы на C с Tcl/Tk";
	label .lab0 -text {strlen(};
	pack .lab0 -anchor {center}  -side {left};
	entry .ent1 ;
	pack .ent1 -anchor {center} -side {left};
	label .lab2  -text {)};
	pack .lab2 -anchor {center} -side {left};
	button .but3  -text {=} -command {lenstr};
	pack .but3 -anchor {center} -side {left};
	entry .ent4  -width {5};
	pack .ent4  -pady {4} -side {top};
	pack .lab0 .ent1 .lab2 .but3 .ent4 -in {.};
	.ent4 delete 0 end;
    ";
    int code;
    Tcl_FindExecutable(argv[0]);
/*Создание tcl-интерпретатора*/
    tcl_interp = Tcl_CreateInterp();
/*Инициализация созданного tcl-интерпретатора*/
    Tcl_Init(tcl_interp);
/*Инициализация Tk-интерпретатора в контексте созданного tcl-интерпретатора*/
    Tk_Init(tcl_interp);
/*Загружаем наш Tcl/Tk код из строки*/
    code = Tcl_Eval(tcl_interp, strtcl);
/*Но Tcl/Tk код можно загрузить и из файла:
    code = Tcl_EvalFile(tcl_interp, filetcl);
*/
/*Добавляем к нашей кнопки вызов процедуры lenstr при ее нажатии*/
    code = Tcl_Eval(tcl_interp, ".but3  configure -command lenstr;");
/*Связываем имя процедуры "lenstr" с функцией lenStr в этом C-коде*/
    Tcl_CreateCommand(tcl_interp, "lenstr", (Tcl_CmdProc *)lenStr, NULL, NULL);
/*Главный цикл обработки событий от виджетов*/
    Tk_MainLoop();
    return 0;
}

Я думаю код не нуждается в дополнительных комментариях. Получить выполняемый код можно следующим образом:

$gcc   -o test_c test_c.c  -ltcl8.6 -ltk8.6
$

Если вы собираетесь писать приложение со сложным GUI, то целесообразно для его проектирования использовать дизайнеры. Это может быть и Vtcl, и TKproE-2.20 и другие. Я бы рекомендовал использовать TKproE. Из сохраненного проекта достаточно взять тело процедуры TKopenWindow и загрузить его с помощью функций Tcl_Eval или Tcl_EvalFile. В первом случае код вставляется в тело программы, например, присваивается переменной strtcl, как в нашем примере. Во втором случае сохраняется в файле и из него загружается.

Естественный вопрос, как обрабатывать события, например, нажатие кнопки. В этом случае ставится соответствие между именем функции в коде tcl (например, в опции –command у виджета button), который был загружен, и функцией в коде программы. В нашем примере это следующая строка:

/*Связываем имя процедуры "lenstr" с функцией lenStr в этом C-коде*/
    Tcl_CreateCommand(tcl_interp, "lenstr", (Tcl_CmdProc *)lenStr, NULL, NULL);

Для обмена данными между tcl-интерпретатором и основной программой на языке C, могут, использоваться функции Tcl_GetVar и Tcl_SetVar (см. пример), Tcl_LinkVar и др.

Для разработки GUI-приложений с использованием Tk-виджетов на языке C++ разработана красивая библиотека CPPTK. Последнее ее обновление вышло в мае текущего года. Но мы будем иметь ввиду предпоследнюю версию, а именно CPPTK-1.0.2.

Использование этой библиотеки для разработки, подчеркиваю, для разработки графических приложений, позволяет забыть об интерфейсах библиотек libtcl и libtk (см. выше). Согласитесь, это немало, учитывая то, что интерфейс библиотеки CPPTK максимально приближен к интерфейсу Tcl/Tk и самое главное прекрасно документирован:

image

И так, библиотека CPPTK позволяет разрабатывать GUI-приложения на классических tk-виджетах. Но она настолько хорошо спроектирована, что перейти, а еще лучше, добавить поддержку тематических виджетов ttk не сосравляет никакого труда, что мы и сделали, добавив в первую очередь поддержку виджетов ttk::notebook и ttk::combobox.

Патч для библиотеки CPPTK-1.0.2 находится здесь

diff -ruN cpptk-1.0.2/base/cpptkbase.cc cpptk-1.0.2_with_ttk/base/cpptkbase.cc
— cpptk-1.0.2/base/cpptkbase.cc 2017-12-12 09:58:00.269337115 +0300
+++ cpptk-1.0.2_with_ttk/base/cpptkbase.cc 2017-12-08 14:41:51.589205618 +0300
@@ -209,11 +209,16 @@
// refresh Tcl variables
linkCpptoTcl();
}
— catch (exception const &e)
+
+/*LISSI*/
+// catch (exception const &e)
+ catch (std::exception const &e)
+
{
Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
return TCL_ERROR;
}
+
return TCL_OK;
}

diff -ruN cpptk-1.0.2/cpptk.cc cpptk-1.0.2_with_ttk/cpptk.cc
— cpptk-1.0.2/cpptk.cc 2017-12-12 09:58:00.268337115 +0300
+++ cpptk-1.0.2_with_ttk/cpptk.cc 2017-12-11 20:10:09.699863718 +0300
@@ -226,6 +226,28 @@

return Expr(str);
}
+/*LISSI*/
+Expr Tk::addtab(string const &w1,
+ string const &w2)
+{
+ string str("");
+ str += w1;
+ str += " add ";
+ str += w2;
+ str += " ";
+ return Expr(str);
+}
+Expr Tk::tab(string const &w1,
+ string const &w2)
+{
+ string str("");
+ str += w1;
+ str += " tab ";
+ str += w2;
+ str += " ";
+ return Expr(str);
+}
+

Expr Tk::panedwindow(string const &name)
{
@@ -254,6 +276,20 @@
str += name;
return Expr(str);
}
+
+/*LISSI*/
+Expr Tk::combobox(string const &name)
+{
+ string str(«ttk::combobox „);
+ str += name;
+ return Expr(str);
+}
+Expr Tk::notebook(string const &name)
+{
+ string str(“ttk::notebook „);
+ str += name;
+ return Expr(str);
+}

Expr Tk::textw(string const &name)
{
diff -ruN cpptk-1.0.2/cpptkconstants.x cpptk-1.0.2_with_ttk/cpptkconstants.x
— cpptk-1.0.2/cpptkconstants.x 2017-12-12 09:58:00.269337115 +0300
+++ cpptk-1.0.2_with_ttk/cpptkconstants.x 2017-12-08 17:51:55.772314308 +0300
@@ -81,6 +81,9 @@
CPPTK_CONSTANT(hourglass)
CPPTK_CONSTANT(horizontal)
CPPTK_CONSTANT(iconbitmap)
+//LISSI
+CPPTK_CONSTANT(iconphoto)
+
CPPTK_CONSTANT(iconic)
CPPTK_CONSTANT(iconify)
CPPTK_CONSTANT(iconmask)
diff -ruN cpptk-1.0.2/cpptk.h cpptk-1.0.2_with_ttk/cpptk.h
— cpptk-1.0.2/cpptk.h 2017-12-12 09:58:00.268337115 +0300
+++ cpptk-1.0.2_with_ttk/cpptk.h 2017-12-08 14:43:29.004206546 +0300
@@ -74,6 +74,12 @@
std::string const &w8 = std::string(),
std::string const &w9 = std::string(),
std::string const &w10 = std::string());
+/*LISSI*/
+details::Expr addtab(std::string const &w1,
+ std::string const &w2 = std::string());
+details::Expr tab(std::string const &w1,
+ std::string const &w2 = std::string());
+

template <typename T>
details::Expr pack(std::string const &option,
@@ -85,6 +91,27 @@
str += details::toString(t);
return details::Expr(str);
}
+/*LISSI*/
+template <typename T>
+details::Expr addtab(std::string const &option,
+ std::string const &w, T const &t)
+{
+ std::string str(“addtab „);
+ str += option; str += “ »;
+ str += w; str += " ";
+ str += details::toString(t);
+ return details::Expr(str);
+}
+template <typename T>
+details::Expr tab(std::string const &option,
+ std::string const &w, T const &t)
+{
+ std::string str(«tab „);
+ str += option; str += “ »;
+ str += w; str += " ";
+ str += details::toString(t);
+ return details::Expr(str);
+}

details::Expr panedwindow(std::string const &name);

@@ -93,6 +120,9 @@
details::Expr scrollbar(std::string const &name);

details::Expr spinbox(std::string const &name);
+/*LISSI*/
+details::Expr combobox(std::string const &name);
+details::Expr notebook(std::string const &name);

details::Expr textw(std::string const &name);

diff -ruN cpptk-1.0.2/cpptkoptions.x cpptk-1.0.2_with_ttk/cpptkoptions.x
— cpptk-1.0.2/cpptkoptions.x 2017-12-12 09:58:00.269337115 +0300
+++ cpptk-1.0.2_with_ttk/cpptkoptions.x 2017-12-08 18:05:51.108322269 +0300
@@ -49,6 +49,9 @@
CPPTK_OPTION(columnspan, false)
CPPTK_OPTION(compositingrule, false)
CPPTK_OPTION(compound, false)
+//LISSI
+CPPTK_OPTION(padding, false)
+
CPPTK_OPTION(confine, false)
CPPTK_OPTION(container, false)
CPPTK_OPTION(cursor, false)
@@ -76,6 +79,9 @@
CPPTK_OPTION(fg, false)
CPPTK_OPTION(fgstipple, false)
CPPTK_OPTION(file, true)
+//LISSI
+CPPTK_OPTION(data, true)
+
CPPTK_OPTION(fill, false)
CPPTK_OPTION(font, false)
// TODO: fontmap option of the canvas postscript command

Этот патч добавляет не только поддержку новых виджетов, то и поддержку режима –data при работе с images (images(create,photo, ''myimage'' –date (''PEM/base64-данные'');). К сожалению, при укладке в спойлер строки +template пришлось заменить на +template <typename T> (в противном случае спойлер неверно отображал текст). Необходимо это учитывать и провести обратную замену.

Применить патч можно следующим образом. Создайте каталог. В него поместите каталог проекта CPPTK. В нем же сохраните, скажем, в файле patchForCPPTK-1.0.2.patch патч из спойлера (с учетом замечания) и, находясь в этом каталоге, примените патч:

$patch –p0 < patchForCPPTK-1.0.2.patch
$

Все, теперь у вас есть библиотека CPPTK с поддержкой новых виджетов. И все же писать GUI вручную неблагодарное дело. Для проектирования самого GUI все же удобно использовать дизайнер TKproE. Для получения из готового tcl-скрипта программы на C++ с библиотекой CPPTK разработан простой tcl-скрипт convertFromTclToCPPTK.tcl:

tcl-скрипт convertFromTclToCPPTK.tcl

#!/usr/bin/tclsh
# 1 — source file from tkproe
#LISSI-Soft
## Procedure: parseConfig
proc ::parseConfig {w data cfile} {
set ldata $data
set len [llength $ldata]
#puts $len
set two ""
set tree ""
set first [lindex $ldata 0]
if { $len > 1 } {
set two [lindex $ldata 1]
}
if { $len > 2 } {
set tree [lindex $ldata 2]
}
if {$first == «wm»} {
set wmstr «wm($two»
for {set i 2} {$i < $len} {incr i} {
set par [lindex $ldata $i]
set a ", "$par""
set wmstr "$wmstr$a"
}
set a ");"
set wmstr "$wmstr$a"
puts "t$wmstr"
return
}
#Определяем widget tk
set tkWid «frame canvas button entry label message listbox text menubutton menu scrollbar scale checkbutton radiobutton toplevel labelframe spinbox panedwindow»
set ttkWid «ttk::notebook ttk::combobox»

set beg [string first $first $tkWid]
if { $beg != -1 } {
set initI 2
set wmstr "t$first ("$two""
# set wmstr "$first("$two""
if { [string range $tree 0 0 ] != "-" } {
set wmstr "$wmstr, "$tree""
incr initI
}
set wmstr "$wmstr) "
set lenstr [string length $wmstr]
for {set i $initI} {$i < $len} {incr i} {
set par [lindex $ldata $i]
incr i
set parVal [lindex $ldata $i]
if { $par == "-variable" || $par == "-textvariable"} {
set wmstr "$wmstr $par ($parVal)"
} else {
set wmstr "$wmstr $par ("$parVal")"
}
incr lenstr [string length $par]
incr lenstr [string length $parVal]
if {$lenstr > 70} {
set wmstr "$wmstrntt"
set lenstr 10
}
}
set wmstr "$wmstr;"
puts $wmstr
return
}
#addTab to notebook
set beg [string first " add ." $data]
if { $beg != -1 } {
set initI 2
set wmstr "taddtab ("$first""
# set wmstr "$first("$two""
if { [string range $tree 0 0 ] != "-" } {
set wmstr "$wmstr, "$tree""
incr initI
}
set wmstr "$wmstr) "

for {set i $initI} {$i < $len} {incr i} {
set par [lindex $ldata $i]
incr i
if { $par == "-image" } {continue}
set parVal [lindex $ldata $i]
if { $par == "-variable" || $par == "-textvariable"} {
set wmstr "$wmstr $par ($parVal)"
} else {
set wmstr "$wmstr $par ("$parVal")"
}
}
set wmstr "$wmstr;"
puts $wmstr
return
}
#ttk::notebook
set beg [string first «ttk::notebook» $data]
if { $beg != -1 } {
set initI 2
set wmstr "tnotebook ("$two""
# set wmstr "$first("$two""
if { [string range $tree 0 0 ] != "-" } {
set wmstr "$wmstr, "$tree""
incr initI
}
set wmstr "$wmstr) "

for {set i $initI} {$i < $len} {incr i} {
set par [lindex $ldata $i]
incr i
# if { $par == "-image" } {continue}
if { $par == "-variable" } {continue}
if { $par == "-textvariable" } {continue}
if { $par == "-takefocus" } {continue}
set parVal [lindex $ldata $i]
set wmstr "$wmstr $par ("$parVal")"
}
set wmstr "$wmstr;"
puts $wmstr
return
}
#ttk::combobox
set beg [string first «ttk::combobox» $data]
if { $beg != -1 } {
set initI 2
set wmstr "tcombobox ("$two""
# set wmstr "$first("$two""
if { [string range $tree 0 0 ] != "-" } {
set wmstr "$wmstr, "$tree""
incr initI
}
set wmstr "$wmstr) "

for {set i $initI} {$i < $len} {incr i} {
set par [lindex $ldata $i]
incr i
# if { $par == "-variable" } {continue}
# if { $par == "-textvariable" } {continue}
if { $par == "-takefocus" } {continue}
# if { $par == "-relwidth" } {continue}
set parVal [lindex $ldata $i]
if { $par == "-variable" || $par == "-textvariable"} {
set wmstr "$wmstr $par ($parVal)"
} else {
set wmstr "$wmstr $par ("$parVal")"
}
}
set wmstr "$wmstr;"
puts $wmstr
return
}
#tkPlace
set tkPlace «tkPlace: pack place grid»
set beg [string first $first $tkPlace]
if { $beg != -1 } {
set tire 0
set initI 2
set wmstr "t$first ("$two""
set lenstr [string length $wmstr]
for {set i $initI} {$i < $len} {incr i} {
set par [lindex $ldata $i]
if { [string range $par 0 0 ] != "-" } {
set wmstr "$wmstr, "$par""
continue
} else {
if { $tire == 0} {
incr tire
set wmstr "$wmstr) "
}
}
if {$tire == 1} {
incr i
}
if { $par == "-variable" } {continue}
if { $par == "-textvariable" } {continue}
if { $par == "-relwidth" } {continue}
if { $par == "-fill" && $first == «pack» } {continue}
set parVal [lindex $ldata $i]
if {$parVal == ".}"} {
set parVal "."
}
set wmstr "$wmstr $par ("$parVal")"
incr lenstr [string length $par]
incr lenstr [string length $parVal]
if {$lenstr > 70} {
set wmstr "$wmstrntt"
set lenstr 10
}
}
set wmstr "$wmstr;"
puts $wmstr
return
}
if {$two == «configure»} {
set wmstr "t"$first" << configure() "
for {set i 2} {$i < $len} {incr i} {
set par [lindex $ldata $i]
incr i
set parVal [lindex $ldata $i]
set wmstr "$wmstr $par ("$parVal")"
}
set wmstr "$wmstr;"
puts $wmstr
return
}
return
}
set largv [llength $argv]
if {$largv != 1} {
puts «Usage: [info script] <file tcl from TKproE>n»
puts «Copyrait LISSI-Soft Ltdn»
exit
}
set fconf [file exists "$argv"]
if { $fconf == «0» } {
puts «File=»$argv" don't existn"
puts «Usage: [info script] <file tcl from Page>n»
puts «Copyrait LISSI-Soft Ltdn»
exit
}
set file $argv
proc findFile {} {
set types {
{«GUI файл» {*.tcl} }
{«Любой файл» *}
}
set file ""
set homeDir $env(HOME)
set file [tk_getOpenFile -filetypes $types -parent. -initialdir $homeDir]
puts «You selected file »$file""
if {[string compare $file ""] == 0} {
return ""
}
}
# read the file one line at a time
set fp [open $file r]
fconfigure $fp -buffering line
puts "//Get file tcl from=$file"
#«proc TPopenWindow»
#«proc TPcloseWindow»
set parseStr 0
puts "//Code for CPP generate LISSI-Soft"
puts "#include «cpptk.h»"
puts "#include <iostream>n"
puts «using namespace Tk;»
puts «using namespace std;n»
puts «int main(int, char *argv[])n{n tryn {ntinit(argv[0]);»

while 1 {
gets $fp data
if [eof $fp] break
if {$data == ""} continue
set com [string range $data 0 0]
if {$com == "n" || $com == "#"} continue
set data [string trim $data]
set len [string first «proc TPopenWindow» $data 0]
if {$len != -1 } {
set parseStr 1
puts "/*$data}*/"
continue
}
set len [string first «proc TPcloseWindow» $data 0]
if {$len != -1 } {
set parseStr 0
puts "/*$data}*/n"
continue
}
if { $parseStr == 0 } {continue}
parseConfig. $data $file
}

puts "trunEventLoop();n }n catch (exception const &e)n {ntcerr << «Error: » << e.what() << '\n';n }n}"

close $fp
exit

Для получения программы на C++ достаточно выполнить этот скрипт:

$ convertFromTclToCPPTK.tcl <tcl-скрипт из TKproE> > <имя файла для сохранения C++ - кода>
$

В качестве примера рассмотрим разработку программы формирования усовершенствованной электронной подписи с библиотекой SSF(«Secure Store and Forward»), используемой в продуктах компании SAP AG для обеспечения криптографической защиту электронных документов за счет использования механизмов электронной подписи и шифрования с использованием российских криптоалгоритмов (ГОСТ 28147-89, ГОСТ Р 34.11-94, ГОСТ Р 34.11-2012, ГОСТ Р 34.10-2001, ГОСТ Р 34.10-2012). Проект GUI в дизайнере TKproE выглядит следующим образом:

image

Скрипт этого проекта находится здесь

# Generated by TKproE 2.20 — Tue Dec 12 12:50:32 MSK 2017
#Add from LISSI-Soft
encoding system utf-8
global myHOME
set myHOME $env(HOME)
# Load all images
# Define named fonts
# Global variable initialization
proc TPinitVars {} {
# Initialize global variables
namespace eval :: {;#Creating namespace ::;}
set {::selectedButton} {}
array set {::vTcl} {}
set ::TPexclusions(user_namespace) {}
set ::TPprojType TCL_TK
}
# Toplevel window procedures
proc TPopenWindow. {} {
# CLONEPATH =.
# Cloned Tue Dec 12 12:50:32 MSK 2017
. configure -background {#00F5FF}
bindtags. {. Tkproe.tcl all}
wm aspect.
wm focusmodel. passive
wm grid.
wm geometry. 723x618+383+57
wm iconmask.
wm iconposition.
wm maxsize. 1585 870
wm minsize. 1 1
wm overrideredirect. 0
wm positionfrom. user
wm resizable. 1 1
wm sizefrom.
wm state. normal
wm transient.
labelframe .lfSSF -borderwidth {4} -foreground {#141312} -relief {ridge} -text {Выберите библиотеку SSF} -background {#FFDEAD} -height {100} -padx {4} -width {100}
entry .lfSSF.entSSF -background {#FFFAFA} -foreground {#141312} -highlightbackground {#ffffff} -highlightcolor {#141312} -selectbackground {#418bd4} -selectforeground {#ffffff} -width {40}
pack .lfSSF.entSSF -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side left
button .lfSSF.butSSF -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -text {Ваш выбор}
pack .lfSSF.butSSF -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 9 -pady 0 -side right
pack .lfSSF -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 10 -side top
pack .lfSSF.entSSF .lfSSF.butSSF -in .lfSSF
ttk::notebook .nbSSF -width {700} -height {400} -padding {7}
.nbSSF state {}
frame .nbSSF.frameNB1 -borderwidth {4} -relief {sunken} -background {#FF7256} -height {30} -highlightbackground {#e0dfde} -highlightcolor {#141312} -width {30}
label .nbSSF.frameNB1.labLogo -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -height {329} -highlightbackground {#e0dfde} -highlightcolor {#141312} -relief {raised} -text {labLogo} -width {509}
pack .nbSSF.frameNB1.labLogo -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 28 -side top
pack .nbSSF.frameNB1.labLogo -in .nbSSF.frameNB1
frame .nbSSF.frameNB2 -borderwidth {2} -relief {raised} -background {#FF4500} -height {30} -highlightbackground {#e0dfde} -highlightcolor {#141312} -pady {19} -width {30}
labelframe .nbSSF.frameNB2.lfSignDoc -borderwidth {4} -foreground {#141312} -relief {ridge} -text {Подписываемый документ} -background {#e0dfde} -height {100} -width {100}
entry .nbSSF.frameNB2.lfSignDoc.entSignDoc -background {#FFFAFA} -foreground {#141312} -highlightbackground {#ffffff} -highlightcolor {#141312} -selectbackground {#418bd4} -selectforeground {#ffffff} -width {40}
pack .nbSSF.frameNB2.lfSignDoc.entSignDoc -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 5 -pady 0 -side left
button .nbSSF.frameNB2.lfSignDoc.butSignDoc -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -text {Выберите}
pack .nbSSF.frameNB2.lfSignDoc.butSignDoc -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 6 -pady 0 -side top
pack .nbSSF.frameNB2.lfSignDoc -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 6 -side top
pack .nbSSF.frameNB2.lfSignDoc.entSignDoc .nbSSF.frameNB2.lfSignDoc.butSignDoc -in .nbSSF.frameNB2.lfSignDoc
labelframe .nbSSF.frameNB2.lfForType -borderwidth {4} -foreground {#141312} -relief {ridge} -text {Формат и тип подписи} -background {#e0dfde} -height {100} -padx {1} -pady {5} -width {100}
ttk::combobox .nbSSF.frameNB2.lfForType.comboFor -values {PKCS7 CADES_BES CADES_XLT1} -cursor {xterm}
.nbSSF.frameNB2.lfForType.comboFor state {}
pack .nbSSF.frameNB2.lfForType.comboFor -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 4 -pady 0 -side left
radiobutton .nbSSF.frameNB2.lfForType.radAtt -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -text {Присоединенная} -value {1}
pack .nbSSF.frameNB2.lfForType.radAtt -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 26 -pady 0 -side left
radiobutton .nbSSF.frameNB2.lfForType.radDet -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -text {Отсоединенная} -value {0}
pack .nbSSF.frameNB2.lfForType.radDet -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 13 -pady 0 -side top
pack .nbSSF.frameNB2.lfForType -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 16 -side top
pack .nbSSF.frameNB2.lfForType.comboFor .nbSSF.frameNB2.lfForType.radAtt .nbSSF.frameNB2.lfForType.radDet -in .nbSSF.frameNB2.lfForType
labelframe .nbSSF.frameNB2.lfCert -borderwidth {4} -foreground {#141312} -relief {ridge} -text {Сертификат для подписи} -background {#e0dfde} -height {100} -width {100}
entry .nbSSF.frameNB2.lfCert.entCert -background {#FFFAFA} -foreground {#141312} -highlightbackground {#ffffff} -highlightcolor {#141312} -selectbackground {#418bd4} -selectforeground {#ffffff} -width {40}
pack .nbSSF.frameNB2.lfCert.entCert -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 9 -pady 0 -side left
button .nbSSF.frameNB2.lfCert.butCert -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -text {Укажите путь}
pack .nbSSF.frameNB2.lfCert.butCert -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side left
pack .nbSSF.frameNB2.lfCert -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 8 -side top
pack .nbSSF.frameNB2.lfCert.entCert .nbSSF.frameNB2.lfCert.butCert -in .nbSSF.frameNB2.lfCert
labelframe .nbSSF.frameNB2.lfAtCert -borderwidth {4} -foreground {#141312} -relief {ridge} -text {Как поступить с сертификатом} -background {#00FF00} -height {100} -width {100}
radiobutton .nbSSF.frameNB2.lfAtCert.radAtCert -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -text {Включить в подпись} -value {1}
pack .nbSSF.frameNB2.lfAtCert.radAtCert -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side left
radiobutton .nbSSF.frameNB2.lfAtCert.radDetCert -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -text {Не включать} -value {0}
pack .nbSSF.frameNB2.lfAtCert.radDetCert -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 10 -pady 0 -side top
pack .nbSSF.frameNB2.lfAtCert -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top
pack .nbSSF.frameNB2.lfAtCert.radAtCert .nbSSF.frameNB2.lfAtCert.radDetCert -in .nbSSF.frameNB2.lfAtCert
button .nbSSF.frameNB2.butSign -activebackground {#e0dfde} -activeforeground {#141312} -background {#20B2AA} -borderwidth {7} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -relief {ridge} -text {Сформировать подпись}
pack .nbSSF.frameNB2.butSign -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 14 -side top
pack .nbSSF.frameNB2.lfSignDoc .nbSSF.frameNB2.lfForType .nbSSF.frameNB2.lfCert .nbSSF.frameNB2.lfAtCert .nbSSF.frameNB2.butSign -in .nbSSF.frameNB2
frame .nbSSF.frameNB3 -borderwidth {2} -relief {raised} -background {#e0dfde} -height {30} -highlightbackground {#e0dfde} -highlightcolor {#141312} -width {30}
pack .nbSSF -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 0 -side top
labelframe .lfP11 -borderwidth {4} -foreground {#141312} -relief {ridge} -text {Хранилище вашего закрытого ключа} -background {#FFE4B5} -height {100} -width {100}
entry .lfP11.entP11 -background {#FFFAFA} -foreground {#141312} -highlightbackground {#ffffff} -highlightcolor {#141312} -selectbackground {#418bd4} -selectforeground {#ffffff} -width {40}
pack .lfP11.entP11 -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 8 -pady 0 -side left
button .lfP11.butP11 -activebackground {#e0dfde} -activeforeground {#141312} -background {#e0dfde} -borderwidth {4} -foreground {#141312} -highlightbackground {#e0dfde} -highlightcolor {#141312} -relief {ridge} -text {Выбор за вами}
pack .lfP11.butP11 -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 9 -pady 1 -side top
pack .lfP11 -anchor center -expand 0 -fill none -ipadx 0 -ipady 0 -padx 0 -pady 14 -side top
pack .lfP11.entP11 .lfP11.butP11 -in .lfP11
.nbSSF add .nbSSF.frameNB1 -padding 0 -sticky nsew -state normal -text Логотип -image {} -compound none -underline -1
.nbSSF add .nbSSF.frameNB2 -padding 0 -sticky nsew -state normal -text Подписать -image {} -compound none -underline -1
.nbSSF add .nbSSF.frameNB3 -padding 0 -sticky nsew -state normal -text Проверить -image {} -compound none -underline -1
pack .lfSSF .nbSSF .lfP11 -in .}
proc TPcloseWindow. {} {
wm state. withdrawn}
# User created procedures
namespace eval :: {
#Creating namespace ::
}
# Display and start the application
if {[info proc TPstartupSrc] != {}} { TPstartupSrc }
TPinitVars
TPopenWindow.
if {[info proc TPendSrc] != {}} { TPendSrc }
# End of TKproE generated code
#P.S. К сожалению при укладке в спойлер символы > пришлось заменить на >
#При сохранении скрипта выполните обратную замену.

Сохранив скрипт в файле, например, forBook.tcl, любой может его загрузить в дизайнер TKproE и увидеть знакомую уже картинку (см. выше). Теперь, чтобы получить код C++ воспользуемся скриптом convertFromTclToCPPTK.tcl:

$ convertFromTclToCPPTK.tcl forBook.tcl >forBook.cc
$

Полученный код forBook.cc можно увидеть здесь

//Get file tcl from=forBook.tcl
//Code for CPP generate LISSI-Soft
#include «cpptk.h»
/*К сожалению при укладке в спойлер в следующей строке пришлось заменить > на >
сделайте обратную замену*/
#include <iostream>
using namespace Tk;
using namespace std;

int main(int, char *argv[])
{
try
{
init(argv[0]);
/*proc TPopenWindow. {} {}*/
"." << configure() -background ("#00F5FF");
wm(aspect, ".");
wm(focusmodel, ".", «passive»);
wm(grid, ".");
wm(geometry, ".", «723x618+383+57»);
wm(iconmask, ".");
wm(iconposition, ".");
wm(maxsize, ".", «1585», «870»);
wm(minsize, ".", «1», «1»);
wm(overrideredirect, ".", «0»);
wm(positionfrom, ".", «user»);
wm(resizable, ".", «1», «1»);
wm(sizefrom, ".");
wm(state, ".", «normal»);
wm(transient, ".");
labelframe (".lfSSF") -borderwidth («4») -foreground ("#141312") -relief («ridge») -text («Выберите библиотеку SSF»)
-background ("#FFDEAD") -height («100») -padx («4») -width («100»);
entry (".lfSSF.entSSF") -background ("#FFFAFA") -foreground ("#141312") -highlightbackground ("#ffffff")
-highlightcolor ("#141312") -selectbackground ("#418bd4") -selectforeground ("#ffffff")
-width («40»);
pack (".lfSSF.entSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («0») -side («left»)
;
button (".lfSSF.butSSF") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Ваш выбор»);
pack (".lfSSF.butSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («9») -pady («0») -side («right»)
;
pack (".lfSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («10») -side («top»)
;
pack (".lfSSF.entSSF", ".lfSSF.butSSF") -in (".lfSSF");
notebook (".nbSSF") -width («700») -height («400») -padding («7»);
frame (".nbSSF.frameNB1") -borderwidth («4») -relief («sunken») -background ("#FF7256")
-height («30») -highlightbackground ("#e0dfde") -highlightcolor ("#141312") -width («30»)
;
label (".nbSSF.frameNB1.labLogo") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -foreground ("#141312") -height («329») -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -relief («raised») -text («labLogo») -width («509»);
pack (".nbSSF.frameNB1.labLogo") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («28») -side («top»);
pack (".nbSSF.frameNB1.labLogo") -in (".nbSSF.frameNB1");
frame (".nbSSF.frameNB2") -borderwidth («2») -relief («raised») -background ("#FF4500")
-height («30») -highlightbackground ("#e0dfde") -highlightcolor ("#141312") -pady («19»)
-width («30»);
labelframe (".nbSSF.frameNB2.lfSignDoc") -borderwidth («4») -foreground ("#141312")
-relief («ridge») -text («Подписываемый документ») -background ("#e0dfde") -height («100»)
-width («100»);
entry (".nbSSF.frameNB2.lfSignDoc.entSignDoc") -background ("#FFFAFA") -foreground ("#141312")
-highlightbackground ("#ffffff") -highlightcolor ("#141312") -selectbackground ("#418bd4")
-selectforeground ("#ffffff") -width («40»);
pack (".nbSSF.frameNB2.lfSignDoc.entSignDoc") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («5») -pady («0») -side («left»);
button (".nbSSF.frameNB2.lfSignDoc.butSignDoc") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Выберите»);
pack (".nbSSF.frameNB2.lfSignDoc.butSignDoc") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («6») -pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfSignDoc") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («6») -side («top»);
pack (".nbSSF.frameNB2.lfSignDoc.entSignDoc", ".nbSSF.frameNB2.lfSignDoc.butSignDoc") -in (".nbSSF.frameNB2.lfSignDoc")
;
labelframe (".nbSSF.frameNB2.lfForType") -borderwidth («4») -foreground ("#141312")
-relief («ridge») -text («Формат и тип подписи») -background ("#e0dfde") -height («100»)
-padx («1») -pady («5») -width («100»);
combobox (".nbSSF.frameNB2.lfForType.comboFor") -values («PKCS7 CADES_BES CADES_XLT1») -cursor («xterm»);
pack (".nbSSF.frameNB2.lfForType.comboFor") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («4») -pady («0») -side («left»);
radiobutton (".nbSSF.frameNB2.lfForType.radAtt") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Присоединенная») -value («1»);
pack (".nbSSF.frameNB2.lfForType.radAtt") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («26») -pady («0») -side («left»);
radiobutton (".nbSSF.frameNB2.lfForType.radDet") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Отсоединенная») -value («0»);
pack (".nbSSF.frameNB2.lfForType.radDet") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («13») -pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfForType") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («16») -side («top»);
pack (".nbSSF.frameNB2.lfForType.comboFor", ".nbSSF.frameNB2.lfForType.radAtt", ".nbSSF.frameNB2.lfForType.radDet") -in (".nbSSF.frameNB2.lfForType")
;
labelframe (".nbSSF.frameNB2.lfCert") -borderwidth («4») -foreground ("#141312") -relief («ridge»)
-text («Сертификат для подписи») -background ("#e0dfde") -height («100») -width («100»)
;
entry (".nbSSF.frameNB2.lfCert.entCert") -background ("#FFFAFA") -foreground ("#141312")
-highlightbackground ("#ffffff") -highlightcolor ("#141312") -selectbackground ("#418bd4")
-selectforeground ("#ffffff") -width («40»);
pack (".nbSSF.frameNB2.lfCert.entCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («9») -pady («0») -side («left»);
button (".nbSSF.frameNB2.lfCert.butCert") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Укажите путь»);
pack (".nbSSF.frameNB2.lfCert.butCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («0») -pady («0») -side («left»);
pack (".nbSSF.frameNB2.lfCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («8») -side («top»);
pack (".nbSSF.frameNB2.lfCert.entCert", ".nbSSF.frameNB2.lfCert.butCert") -in (".nbSSF.frameNB2.lfCert");
labelframe (".nbSSF.frameNB2.lfAtCert") -borderwidth («4») -foreground ("#141312")
-relief («ridge») -text («Как поступить с сертификатом») -background ("#00FF00")
-height («100») -width («100»);
radiobutton (".nbSSF.frameNB2.lfAtCert.radAtCert") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Включить в подпись») -value («1»);
pack (".nbSSF.frameNB2.lfAtCert.radAtCert") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («0») -pady («0») -side («left»);
radiobutton (".nbSSF.frameNB2.lfAtCert.radDetCert") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Не включать») -value («0»);
pack (".nbSSF.frameNB2.lfAtCert.radDetCert") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («10») -pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfAtCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfAtCert.radAtCert", ".nbSSF.frameNB2.lfAtCert.radDetCert") -in (".nbSSF.frameNB2.lfAtCert");
button (".nbSSF.frameNB2.butSign") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#20B2AA") -borderwidth («7») -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -relief («ridge») -text («Сформировать подпись»);
pack (".nbSSF.frameNB2.butSign") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («14») -side («top»);
pack (".nbSSF.frameNB2.lfSignDoc", ".nbSSF.frameNB2.lfForType", ".nbSSF.frameNB2.lfCert", ".nbSSF.frameNB2.lfAtCert", ".nbSSF.frameNB2.butSign") -in (".nbSSF.frameNB2");
frame (".nbSSF.frameNB3") -borderwidth («2») -relief («raised») -background ("#e0dfde")
-height («30») -highlightbackground ("#e0dfde") -highlightcolor ("#141312") -width («30»)
;
pack (".nbSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («0») -side («top»);
labelframe (".lfP11") -borderwidth («4») -foreground ("#141312") -relief («ridge») -text («Хранилище вашего закрытого ключа»)
-background ("#FFE4B5") -height («100») -width («100»);
entry (".lfP11.entP11") -background ("#FFFAFA") -foreground ("#141312") -highlightbackground ("#ffffff")
-highlightcolor ("#141312") -selectbackground ("#418bd4") -selectforeground ("#ffffff")
-width («40»);
pack (".lfP11.entP11") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («8») -pady («0») -side («left»)
;
button (".lfP11.butP11") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -borderwidth («4») -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -relief («ridge») -text («Выбор за вами»);
pack (".lfP11.butP11") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («9») -pady («1») -side («top»)
;
pack (".lfP11") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («14») -side («top»)
;
pack (".lfP11.entP11", ".lfP11.butP11") -in (".lfP11");
addtab (".nbSSF", ".nbSSF.frameNB1") -padding («0») -sticky («nsew») -state («normal») -text («Логотип») -compound («none») -underline ("-1");
addtab (".nbSSF", ".nbSSF.frameNB2") -padding («0») -sticky («nsew») -state («normal») -text («Подписать») -compound («none») -underline ("-1");
addtab (".nbSSF", ".nbSSF.frameNB3") -padding («0») -sticky («nsew») -state («normal») -text («Проверить») -compound («none») -underline ("-1");
pack (".lfSSF", ".nbSSF", ".lfP11") -in (".");
/*proc TPcloseWindow. {} {}*/

runEventLoop();
}
catch (exception const &e)
{
cerr << «Error: » << e.what() << 'n';
}
}

Для получения банарного кода положим файл forBook.cc в каталог с пропатченной библиотекой CPPTK (см.выше) и выполним следующую команду:

$ g++  -DUSE_INTERP_RESULT cpptk.cc base/cpptkbase.cc -o forBook forBook.cc -I./cpptk -Ibase -ltcl8.6 -ltk8.6 –pthread
$

Если теперь запустить полученный бинарный модуль forBook, то на экране монитора мы увидим знакомое изображение (см. выше). К сожалению, нажатие кнопок не приведет ни к какому результату, да и иконка нас не устраивает. И мы дописываем полученную программу. Включаем в нее код иконки:

images(create, photo, "stamp_32x32") -data (
"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr …
");

Привязываем ее к главному окну:

	wm (iconphoto, ".",  "stamp_32x32");

Но самое главное, что мы делаем, это привязываем к кнопкам определенные функции, которые необходимо будет выполнить при их нажатии:

        ".lfSSF.butSSF" << configure () -command (compute);
	".nbSSF.frameNB2.lfSignDoc.butSignDoc" << configure () -command (findDoc);
	".nbSSF.frameNB2.lfCert.butCert" << configure () -command (findCert);
	".lfP11.butP11" << configure () -command (findPrivKey);
	".nbSSF.frameNB2.lfForType.radAtt"  << configure () -command (updateRad);
	".nbSSF.frameNB2.lfForType.radDet"  << configure () -command (updateRad);
	".nbSSF.frameNB2.lfAtCert.radAtCert"  << configure () -command (updateRad);
	".nbSSF.frameNB2.lfAtCert.radDetCert"  << configure () -command (updateRad);
	".nbSSF.frameNB2.butSign"  << configure () -command (createSign);

Естественно, пишем код самих функций.

В законченном виде код выглядит так

//Get file tcl from=GUIforSSFfromPAGE_PACK.tcl
//Code for CPP generate LISSI-Soft
#include «cpptk.h»
/*К сожалению при укладке в спойлер в следующей строке пришлось заменить > на >
сделайте обратную замену*/
#include <iostream>

using namespace Tk;
using namespace std;
string str;
string selSignType = «1»;
string selCert = «1»;
int len;
void compute()
{
string fileName(tk_getOpenFile() -filetypes ("{{Библиотека SSF} {.so}} {{Библиотека SSF MS} {.dll}} {{Любой файл} {*}}"));
".lfSSF.entSSF" << deleteentry (0, end);
".lfSSF.entSSF" << insert(end, fileName.c_str());
// ".nbSSF.frameNB2" << configure () -state (normal);
// ".nbSSF.frameNB3" << configure () -state (normal);
tab (".nbSSF", ".nbSSF.frameNB2") -state («normal»);
tab (".nbSSF", ".nbSSF.frameNB3") -state («normal»);
".nbSSF" << select (".nbSSF.frameNB2");
cout << «Hello Button C++/Tk!» << endl;
/*К сожалению при укладке в спойлер в следующей строке пришлось заменить > на >
сделайте обратную замену*/
len = static_cast<int>(str.size());
}
void findDoc()
{
string fileName(tk_getOpenFile() -filetypes ("{{Документ для подписи} {.doc}} {{Текстовый документ} {.txt}} {{Любой документ} {*}}"));
".nbSSF.frameNB2.lfSignDoc.entSignDoc" << deleteentry (0, end);
".nbSSF.frameNB2.lfSignDoc.entSignDoc" << insert(end, fileName.c_str());
}
void findCert()
{
string fileName(tk_getOpenFile() -filetypes ("{{Сертификат в формате DER} {.der}} {{Сертификат в формате DER} {.cer}}
{{Сертификат в формате PEM} {.pem}} {{Сертификат в формате PEM} {.crt}} {{Любой файл} {*}}"));
".nbSSF.frameNB2.lfCert.entCert" << deleteentry (0, end);
".nbSSF.frameNB2.lfCert.entCert" << insert(end, fileName.c_str());
".lfP11.butP11" << configure () -state (normal);
}
void findPrivKey()
{
string fileName(tk_getOpenFile() -filetypes ("{{Хранилище в PKCS#12} {.p12}} {{Хранилище в PKCS#12} {.pfx}}
{{Библиотека PKCS#11} {.so}} {{Библиотека PKCS#11 MS} {.dll}} {{Любой файл} {*}}"));
".lfP11.entP11" << deleteentry (0, end);
".lfP11.entP11" << insert(end, fileName.c_str());
".nbSSF.frameNB2.butSign" << configure () -state (normal);

}
void updateRad()
{

".nbSSF.frameNB2.lfForType.radAtt" << configure () -state (normal);
".nbSSF.frameNB2.lfForType.radDet" << configure () -state (normal);
".nbSSF.frameNB2.lfAtCert.radAtCert" << configure () -state (normal);
".nbSSF.frameNB2.lfAtCert.radDetCert" << configure () -state (normal);
// update();
}
void createSign()
{
char mesSign [1000];
cout << «Формирование подписи» << endl;
cout << selSignType.c_str() << endl;
cout << selCert.c_str() << endl;
// string response(tk_dialog(".", «Будете подписывать?», «Вы собираетесь подписать файлnn», warning, «OK», «OK», «Cancel»));
string content(".nbSSF.frameNB2.lfSignDoc.entSignDoc" << get());
strcpy(mesSign, «Вы собираетесь подписать файлn»);
if (strlen (content.c_str()) == 0)
return;
strcat(mesSign, content.c_str());
strcat(mesSign, "nФормат подписи = ");
string content1(".nbSSF.frameNB2.lfForType.comboFor" << get());
strcat(mesSign, content1.c_str());
if (strcmp(selSignType.c_str(), «1»)) {
strcat(mesSign, "nПодпись не будет содержать документаn");
} else {
strcat(mesSign, "nДокумент включается в подписьn");
}
strcat(mesSign, «Ваш сертификат из файлаn»);
string content2(".nbSSF.frameNB2.lfCert.entCert" << get());
if (strlen (content2.c_str()) == 0)
return;
strcat(mesSign, content2.c_str());
if (strcmp(selCert.c_str(), «1»)) {
strcat(mesSign, "nНе будет включен в подписьn");
} else {
strcat(mesSign, "nбудет включен в подписьn");
}
strcat(mesSign, «Ваш закрытый ключ будет будет получен посредствомnn»);
string content3(".lfP11.entP11" << get());
if (strlen (content3.c_str()) == 0)
return;
strcat(mesSign, content3.c_str());
string response(tk_messageBox() -title(«Подписываем документ») -icon(question) -messagetext (mesSign) -messagetype (okcancel));
cout << response.c_str() << endl;

}

int main(int, char *argv[])
{
try
{
images(create, photo, «stamp_32x32») -data (
«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
RK5CYII=»);
init(argv[0]);
/*proc TPopenWindow. {} {}*/
"." << configure() -background ("#00F5FF");
fonts( configure, «TkDefaultFont») -size(12);
wm(title, ".", «Формирование Электронной Подписи (PKCS7, CADES_BES, CADES_XLT1)»);
wm(aspect, ".");
wm(focusmodel, ".", «passive»);
wm(grid, ".");
wm(geometry, ".", «723x618+383+57»);
wm(iconmask, ".");
wm(iconposition, ".");
wm(maxsize, ".", «1585», «870»);
wm(minsize, ".", «1», «1»);
wm(overrideredirect, ".", «0»);
wm(positionfrom, ".", «user»);
wm(resizable, ".", «1», «1»);
wm(sizefrom, ".");
wm(state, ".", «normal»);
wm(transient, ".");
labelframe (".lfSSF") -borderwidth («4») -foreground ("#141312") -relief («ridge») -text («Выберите библиотеку SSF»)
-background ("#FFDEAD") -height («100») -padx («4») -width («100»);
entry (".lfSSF.entSSF") -background ("#FFFAFA") -foreground ("#141312") -highlightbackground ("#ffffff")
-highlightcolor ("#141312") -selectbackground ("#418bd4") -selectforeground ("#ffffff")
-width («40»);
pack (".lfSSF.entSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («0») -side («left»)
;
button (".lfSSF.butSSF") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Ваш выбор»);
pack (".lfSSF.butSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («9») -pady («0») -side («right»)
;
pack (".lfSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («10») -side («top»)
;
pack (".lfSSF.entSSF", ".lfSSF.butSSF") -in (".lfSSF");
notebook (".nbSSF") -width («700») -height («400») -padding («7»);
frame (".nbSSF.frameNB1") -borderwidth («4») -relief («sunken») -background ("#FF7256")
-height («30») -highlightbackground ("#e0dfde") -highlightcolor ("#141312") -width («30»)
;
label (".nbSSF.frameNB1.labLogo") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -foreground ("#141312") -height («329») -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -relief («raised») -text («Здесь должен быть ваш логотип»)
-width («509»);
pack (".nbSSF.frameNB1.labLogo") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («28») -side («top»);
pack (".nbSSF.frameNB1.labLogo") -in (".nbSSF.frameNB1");
frame (".nbSSF.frameNB2") -borderwidth («2») -relief («raised») -background ("#FF4500")
-height («30») -highlightbackground ("#e0dfde") -highlightcolor ("#141312") -pady («19»)
-width («30»);
labelframe (".nbSSF.frameNB2.lfSignDoc") -borderwidth («4») -foreground ("#141312")
-relief («ridge») -text («Подписываемый документ») -background ("#e0dfde") -height («100»)
-width («100»);
entry (".nbSSF.frameNB2.lfSignDoc.entSignDoc") -background ("#FFFAFA") -foreground ("#141312")
-highlightbackground ("#ffffff") -highlightcolor ("#141312") -selectbackground ("#418bd4")
-selectforeground ("#ffffff") -width («40»);
pack (".nbSSF.frameNB2.lfSignDoc.entSignDoc") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («5») -pady («0») -side («left»);
button (".nbSSF.frameNB2.lfSignDoc.butSignDoc") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Выберите»);
pack (".nbSSF.frameNB2.lfSignDoc.butSignDoc") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («6») -pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfSignDoc") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («6») -side («top»);
pack (".nbSSF.frameNB2.lfSignDoc.entSignDoc", ".nbSSF.frameNB2.lfSignDoc.butSignDoc") -in (".nbSSF.frameNB2.lfSignDoc")
;
labelframe (".nbSSF.frameNB2.lfForType") -borderwidth («4») -foreground ("#141312")
-relief («ridge») -text («Формат и тип подписи») -background ("#e0dfde") -height («100»)
-padx («1») -pady («5») -width («100»);
combobox (".nbSSF.frameNB2.lfForType.comboFor") -values («PKCS7 CADES_BES CADES_XLT1») -cursor («xterm»);
pack (".nbSSF.frameNB2.lfForType.comboFor") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («4») -pady («0») -side («left»);
radiobutton (".nbSSF.frameNB2.lfForType.radAtt") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Присоединенная») -value («1») -variable (selSignType)
;
pack (".nbSSF.frameNB2.lfForType.radAtt") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («26») -pady («0») -side («left»);
radiobutton (".nbSSF.frameNB2.lfForType.radDet") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Отсоединенная») -value («0») -variable (selSignType)
;
pack (".nbSSF.frameNB2.lfForType.radDet") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («13») -pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfForType") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («16») -side («top»);
pack (".nbSSF.frameNB2.lfForType.comboFor", ".nbSSF.frameNB2.lfForType.radAtt", ".nbSSF.frameNB2.lfForType.radDet") -in (".nbSSF.frameNB2.lfForType")
;
labelframe (".nbSSF.frameNB2.lfCert") -borderwidth («4») -foreground ("#141312") -relief («ridge»)
-text («Сертификат для подписи») -background ("#e0dfde") -height («100») -width («100»)
;
entry (".nbSSF.frameNB2.lfCert.entCert") -background ("#FFFAFA") -foreground ("#141312")
-highlightbackground ("#ffffff") -highlightcolor ("#141312") -selectbackground ("#418bd4")
-selectforeground ("#ffffff") -width («40»);
pack (".nbSSF.frameNB2.lfCert.entCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («9») -pady («0») -side («left»);
button (".nbSSF.frameNB2.lfCert.butCert") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Укажите путь»);
pack (".nbSSF.frameNB2.lfCert.butCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0»)
-padx («0») -pady («0») -side («left»);
pack (".nbSSF.frameNB2.lfCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («8») -side («top»);
pack (".nbSSF.frameNB2.lfCert.entCert", ".nbSSF.frameNB2.lfCert.butCert") -in (".nbSSF.frameNB2.lfCert");
labelframe (".nbSSF.frameNB2.lfAtCert") -borderwidth («4») -foreground ("#141312")
-relief («ridge») -text («Как поступить с сертификатом») -background ("#00FF00")
-height («100») -width («100»);
radiobutton (".nbSSF.frameNB2.lfAtCert.radAtCert") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Включить в подпись») -value («1») -variable (selCert)
;
pack (".nbSSF.frameNB2.lfAtCert.radAtCert") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («0») -pady («0») -side («left»);
radiobutton (".nbSSF.frameNB2.lfAtCert.radDetCert") -activebackground ("#e0dfde")
-activeforeground ("#141312") -background ("#e0dfde") -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -text («Не включать») -value («0») -variable (selCert)
;
pack (".nbSSF.frameNB2.lfAtCert.radDetCert") -anchor («center») -expand («0») -ipadx («0»)
-ipady («0») -padx («10») -pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfAtCert") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («0») -side («top»);
pack (".nbSSF.frameNB2.lfAtCert.radAtCert", ".nbSSF.frameNB2.lfAtCert.radDetCert") -in (".nbSSF.frameNB2.lfAtCert");
button (".nbSSF.frameNB2.butSign") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#20B2AA") -borderwidth («7») -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -relief («ridge») -text («Сформировать подпись»)
-image («stamp_32x32») -compound(«left»);
pack (".nbSSF.frameNB2.butSign") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0»)
-pady («14») -side («top»);
pack (".nbSSF.frameNB2.lfSignDoc", ".nbSSF.frameNB2.lfForType", ".nbSSF.frameNB2.lfCert", ".nbSSF.frameNB2.lfAtCert", ".nbSSF.frameNB2.butSign") -in (".nbSSF.frameNB2");
frame (".nbSSF.frameNB3") -borderwidth («2») -relief («raised») -background ("#e0dfde")
-height («30») -highlightbackground ("#e0dfde") -highlightcolor ("#141312") -width («30»)
;
pack (".nbSSF") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («0») -side («top»);
labelframe (".lfP11") -borderwidth («4») -foreground ("#141312") -relief («ridge») -text («Хранилище вашего закрытого ключа»)
-background ("#FFE4B5") -height («100») -width («100»);
entry (".lfP11.entP11") -background ("#FFFAFA") -foreground ("#141312") -highlightbackground ("#ffffff")
-highlightcolor ("#141312") -selectbackground ("#418bd4") -selectforeground ("#ffffff")
-width («40»);
pack (".lfP11.entP11") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («8») -pady («0») -side («left»)
;
button (".lfP11.butP11") -activebackground ("#e0dfde") -activeforeground ("#141312")
-background ("#e0dfde") -borderwidth («4») -foreground ("#141312") -highlightbackground ("#e0dfde")
-highlightcolor ("#141312") -relief («ridge») -text («Выбор за вами»);
pack (".lfP11.butP11") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («9») -pady («1») -side («top»)
;
pack (".lfP11") -anchor («center») -expand («0») -ipadx («0») -ipady («0») -padx («0») -pady («14») -side («top»)
;
pack (".lfP11.entP11", ".lfP11.butP11") -in (".lfP11");
addtab (".nbSSF", ".nbSSF.frameNB1") -padding («0») -sticky («nsew») -state («normal») -text («Логотип») -compound («none») -underline ("-1");
addtab (".nbSSF", ".nbSSF.frameNB2") -padding («0») -sticky («nsew») -state («normal») -text («Подписать») -compound («none») -underline ("-1");
addtab (".nbSSF", ".nbSSF.frameNB3") -padding («0») -sticky («nsew») -state («normal») -text («Проверить») -compound («none») -underline ("-1");
pack (".lfSSF", ".nbSSF", ".lfP11") -in (".");
/*proc TPcloseWindow. {} {}*/
".lfSSF.butSSF" << configure () -command (compute);
".nbSSF.frameNB2.lfSignDoc.butSignDoc" << configure () -command (findDoc);
".nbSSF.frameNB2.lfCert.butCert" << configure () -command (findCert);
".lfP11.butP11" << configure () -command (findPrivKey);
".nbSSF.frameNB2.lfForType.radAtt" << configure () -command (updateRad);
".nbSSF.frameNB2.lfForType.radDet" << configure () -command (updateRad);
".nbSSF.frameNB2.lfAtCert.radAtCert" << configure () -command (updateRad);
".nbSSF.frameNB2.lfAtCert.radDetCert" << configure () -command (updateRad);
".nbSSF.frameNB2.butSign" << configure () -command (createSign);
".nbSSF.frameNB2.butSign" << configure () -state (disabled);
".lfP11.butP11" << configure () -state (disabled);
".nbSSF.frameNB2.lfForType.comboFor" << deleteentry (0, end);
".nbSSF.frameNB2.lfForType.comboFor" << insert(end, «PKCS7»);
tab (".nbSSF", ".nbSSF.frameNB2") -state (disabled);
tab (".nbSSF", ".nbSSF.frameNB3") -state (disabled);
wm (iconphoto, ".", «stamp_32x32»);

runEventLoop();
}
catch (exception const &e)
{
cerr << «Error: » << e.what() << 'n';
}
}

И после получения бинарного кода запускаем его и видим следующее:

image

Вот и все. Но остались еще две вещи, про которые я хотел бы рассказать. Это создание расширений для Tcl посредством динамических библиотек и Tcl/Tk в Android.

Автор: saipr

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js