Разработка приложений на языках C/C++ с использованием 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] = '\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 "$wmstr\n\t\t"
    	    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 "$wmstr\n\t\t"
    	    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 Ltd\n"
        exit
    }
    set fconf [file exists "$argv"]
    if { $fconf == "0" } {
        puts "File=\"$argv\" don't exist\n"
        puts "Usage: [info script] <file tcl from Page\>\n"
        puts "Copyrait LISSI-Soft Ltd\n"
        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  try\n  {\n\tinit(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  {\n\tcerr << \"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. К сожалению при укладке в спойлер символы > пришлось заменить на \>
    #При сохранении скрипта выполните обратную замену.
    </spoiler>
    Сохранив скрипт в файле, например, forBook.tcl, любой  может его загрузить в дизайнер TKproE и увидеть знакомую уже картинку (см. выше). Теперь, чтобы получить код C++ воспользуемся скриптом convertFromTclToCPPTK.tcl:
    
    <source lang="bash">$ 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(".", "Будете подписывать?", "Вы собираетесь подписать файл\n\n", 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, "Ваш закрытый ключ будет будет получен посредством\n\n");
        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 (
    "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACEdJREFUeNqUV3toVPkVPvc5d+68MuNM\
    xiTG1TWrLj5WyL50cTViC3YVRba0tGxbWNdS2Nr6VwutpRUpFPrfQl2QQu2CpWC1uouFLla6utqo8bmxxhjzmrxnknlkcmfmvvqdeyPINrbjHQ6/m5s7v/Od73znnN8I\
    ruvSl6/+q51UyU1TanGaguEITY6O0Wwut5Qqxk9n797dUrh/P0SCUJU1rRBMJmWy7fRMb682MmfcXv2D/d9d+fprw5mr12kmm6MVG9spoAfJdRxqXdv+X75k+h+XwB9J\
    JLtibA6L4onZGzeW2F1dpBoG1bBhBe9YAwOkYI0hELFQ6Mic+NPp9PLl21zHLZIo0v+7ng4AxJjY1MrmXlUM40z21Kn40OXLNG5ZNDE3R8VqlUzbJlkQKRxQKR0KUWss\
    Rg39g+03Dx/5y6KOrQfFeOIL8TEI4VkBIPLCyGh7UKBTk6dPx+9cuEA95TJNI3pZkkiTZQqoKnEKC2aNclmD+vN5Wp1M0tKJie1zp/96Pbs4fbpl7ar9ciBQcmz3GQAA\
    tWsY7weJfj155kzk2qefUnehQI4g0OJIhDQAEHyS/MAEP7xyrUbdE+NUMU1ak0oFirduf/Pm2b9dfvEr2z8wjQo9t34BVwv5Lw8ObrR7ez8YPno00n3+PD0olUiC05Zw\
    mIIinLNwXd8564Q3UUSBUiGd0khDppCngZkZSmoaGffu7bChF7Kt+hmY6Ly6R7x+jUpDwzRQqRB/tUkPzUdLvkthHgCih2+SwZoEPcS0IDYVaLRYpGQ6TUpf35ZaNtve\
    um5t14JkL/SwNDjYAvHRDOcXOU8gElmAymESnLHJnlPBMwWssKlgiUXZoOukQiPTEGrKcfQHRz88Ua1WF9cNQFEVCxflEb2EyEKy5FHNEUreKvgrvq7g2WPnKq94nzXS\
    EAxSBZqQtABpfX0rP//dh4frTgE2j7hQeBViUrAhU+oy8YJv3gcMiHAuSz4AXjkN3v/Z8P25CkoV+Y9BG/++fr2jbgB2qbTad0ReZAyCFc8ORVHwV2ZB9AFwWfoamHdO\
    fppsBdsDHL9n5vPJugEUBgebG2pVCmDjGnSges3Ed+gBYGfzJj9xz8CE+fq0XYE0sKAg+hqqwo1Gs3VrwE6nb9dmZ0lHBAp25DwHJN84v1+2wHz+mSl+l4UpAXh4UYIC\
    QZ2yhSLpa9ZcqhvAi/ve/UlZCxphSSYVABzX8eqfmWAL4D4g+oCUeRYeV4RfJQCNKogvf55ms1kaCodKG7/3nd/WDUCLxTqDGzacVBFFRFHIQs/nWle8khP91cv7YxO9\
    8pN4Q3xHw/QLNTWRjMbVPTk5t+lXv/zWqvYN3XUDqKGJaK2t/+SERgGAaTbQyWSPXl9UXimyU9EvSU8ljk1BdEIFzSj5xhv0sLOTUnt2H1n20kufDN97QHUDwIyn0KqV\
    d/MYMmE4CLMW4KQCEC7SIZHfkETX9pwKWCUZ/SLVSCpEF9++nUo9PTSSydSaXnn5z9NjY1TIz9QPIJZO0QtbNndRR8exB/kCmdyQEDH3A+7rPKYdrgqoXMUY1uMJCi1K\
    ktbcTJGObVS4d4+Gz50js7mpV1ADgyVMyTmIuu4y1CJhkmXZXrl37/6rsnJ2fGJim9rX945ULiebolGS1YA3ron7fkMDqfE4SYkE2UjNwKlTlOu5T301k1Z87a0/rF63\
    3q7h/PDUQ89CR7Lswx4SQP3Drtt8FKO0LEdGjx3rG5meTpUwG3gqhjAfRJiDlltEx8xOTVERZnPVNDY+iry5+fCuffs+Sjc2OtzW+WpY0VYfA7WeXq/ztQQCpLa10ci5\
    cwftYjHViCHDjeY+KFWRCgfgKxwAIo8CSAxMRFF+YiLhrHlzy3FnbJymprL0OMi6AZgVw5/3UH85OxmbuHLl+w42LmG4hCSFljXEyYD4uOx07vnVmufE4Q4IbVijY23Z\
    O3febd34+u+N/OxTj2NPFSE8ez2cKc7evvuNajbXbGB303aoisj5hJsEOzEAZMcmKqMCQCaqYRYg+SA7fOnSgWq5rDBLDvoIW90AXIxfF/VvmpYy0dn5voAynENJgnT0\
    eJss16e/jNwb8/nlAypPPhNAKqDPyGTWZx/17whApBJSx1Y3AD6/udhw8sbNnUZmeF0FFNbwtw0WLJjNUcGZEIsNmYJQYTDsmI3BcaqY9cHPLh6o4d6ybM/qBiAgehfC\
    Gv/XlR9KSEexUvMce84dP9dMqdbUfN6S5WlOQ41T5PhrFc6qUGuh90FHtrdno4iu5drmMwBAbqd7H26a6+/fWkU51tABVeSVhxJHyQplIHpL82eOqk46HjjHY8k7CwB8\
    CemxqzWx/+LnBwQIlzVVvwYQ4fCliwdl2xFsbBpCBUh4FlVUT9HsEE3HDSQSXYKuZzgdlkveyUjEvYj7ABhQIdRcd/ee7EimzZGeAcDM4MD68Rs33i66rmkG9YvqsmU/\
    ev6db+90E/HxKI9iFqmqFIPJ1EM5Guu3wIqOZ45l0nM73/pN29ff3i2kUsdLgjCan8ppff+48DNZketvxfmhoQ3Rtraf6+mmM5IsfcGCXPLqy/gNau/oPv7Rx3FFXmJp\
    2pioqoYSCfeaqAT+4aMuaT2ydtfOQ/mhDM1OTZ21THNRpVjsMArFTXbVbOCt6wIQaWn9o4NebsMs/BxjABYOmIqu32resnXX+LXOvwcEcZrToScSj7J454XtXz2ihSKH\
    LLRqG8pH/yVZUXLxpa0nlaB+Uo9FxWdoRMgzRMQN58mLn0UWp2+98uMDe5Nr13zCTrRodPi19977xbrduw+x4ydni9cd8Y7rNyFnIVf/EWAAwHrdLpsoojQAAAAASUVO\
    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.
    Поделиться публикацией
    Похожие публикации
    Ой, у вас баннер убежал!

    Ну, и что?
    Реклама
    Комментарии 28
    • –5
      Я понимаю так: программирование — это создание программ, реализующих определённую логику работы. Создание графических форм это «не вполне» программирование. Это как-бы сопутствующая программированию сфера.
      Статья не представляет собой ничего полезного, больше похожа на вводную главу какого-то учебника по Tcl/Tk. Вот если бы автор написал какую-нибудь полезную утилиту и выложил здесь исходный код с разбором, тогда польза была бы.
      • 0

        Это или это, а может это может устроить?
        Создание форм — не программирование. Могу согласиться. А вот разработать логику этих форм, заставить выполнять главную задачу и как их создать с минимальными усилиями — это все программирование с Большой буквы. Да и без путеводителя тяжело программировать

        • –3
          Это или это, а может это может устроить?

          Нет не может! Это коммерческие продукты с закрытым исходным кодом.
          С таким же успехом, Я мог бы написать бесполезную статью про Qt, с приведение нескольких «учебных» примеров о том, как создавать формочки с кнопочками.
          Сам таким заниматься не буду, если хотите вот вам ссылка на страницу документации. Переведите на русский язык и будет ещё одна статья: «Разработка приложений на языках C/C++ с использованием Qt»
          • 0

            А про Qt мы знаем начиная с 1.14. И где вы увидели коммерческие продукты? Качайте, изучайте код и т.д. Т.е. вы хотите сказать, что все учебники, все статьи про так как можно и что можно использовать, бесполезны? Интересно, а как вы училися! Кстати, и про Qt статья с примерами не помешала бы и кому-то очень бы помогла. Напишите и вам скажут спасибо.

            • –1
              Вот как раз таки учебники — полезны, а ваша статья бесполезна. Если Я решу изучить Tcl/Tk, то найду официальную документацию и буду читать. Или книгу, которая даст полную информацию о предмете. А собирать у себя в голове «мозаику» из таких вот информационных фрагментов, как ваша статья, нет смысла.
              • 0

                Я вам помогу, вот самая свежая книга:


                image


                Написана прекрасно.

        • +5
          Создание графических форм это «не вполне» программирование. Это как-бы сопутствующая программированию сфера.

          Не согласен с Вами. Задачи человеко-машинного интерфейса очень важны и влияют на решение задачи в целом (ведь, логику работы определяют люди, использую её как инструмент для решения своих задач): как будут подаваться данные в машину, сколько нужно выполнить операций для того, чтобы вбить массив данных из сотни или тысячи элементов, а как эти данные будут отображаться, как их отобразить из оперативной памяти или жесткого диска? Автор статьи показывает нам одно из таких решений — Tcl/Tk. Поэтому считаю, что статья является полезной и даже очень познавательной. Используя полученные данные можно уже создавать свои приложения с использованием этой замечательной технологии.
        • +1

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

          • +3
            Скажите пожалуйста, каков практический смысл использовать С89 в 2017 году?
            Сужу по объявлению всех переменных в начале функций и по отсутствию однострочных комментариев:

            int lenStr(){
                int code;
                int len;
                char slen[256];
                char *res;
            /*Читаем из widget-а введенную строку в переменную tcl с именем a*/
                code = Tcl_Eval(tcl_interp, "set a [.ent1 get];");
            • –2

              В классике.

              • +1
                Что вы имеете в виду?
                • 0

                  Ну, типо, классики написали этот код, а ты просто скопировал и даже тривиальные изменения поленился сделать.

                  • 0

                    Это какой код классики написали, чтобы я понимал? Так ты приведи этот код, в который "даже тривиальные изнемения" не внесли. Хотя классики и писали для того, чтобы на их коде учились, другие, например, ты.

            • 0
              Как-то громоздко все получилось, а преимуществ каких-то особых не видно. Не проще взять тот же Python+Tkinter? Сдается мне, в последнем случае код будет на порядок компактнее и проще при одном и том же выхлопе.
              • 0

                Вы о чем? Python + Tkinter = Tcl/Tk только со всеми недостатками (вот уж где громоздость так громоздкость). И как может быть на порядок компактнее, если Tkinter с Python это фактически просто обертка вокруг Tcl/Tk.
                Вот здесь и здесь есть про Python + Tkinter.

                • 0
                  Спасибо, я в курсе про Python + Tkinter. Вот только не в курсе про недостатки. Зато разработка и отлов ошибок на порядок проще на питоне, нежели на той лапше (уж простите) сишного кода, который вы привели в статье. Если вы это делаете just for fun, то окей, вопросов нет, а если для практических целей, то в чем смысл, если тоже самое можно реализовать так же кроссплатформенно, но на порядок проще?
                  • 0

                    Си это Си, Python это Python. Если вы возьмете "эту лапшу" и положите на Pyton получите один в один тот же код!!! С точностью до синтаксиса. И ошибка для Tk-GUI отлавливаются абсолюно одинаково, их ловит Tcl/Tk.
                    Не знаю с чем спорить? Есть задачи, которые можно решить и на скриптовых языках, на Python-e (но поверьте это лучше делать на Tcl) например, а есть задачи которые решаются только и только на C/C++.

                    • 0
                      Почему? На питоне я этот же интерфейс сделаю по-питоновски, мне же не нужно брать тиклевский скрипт и грузить его в интерпретатор. Под использованием Python + Tkinter я имел ввиду все тоже самое сделать на питоне через виджеты Ткинтера, красиво и чисто, плюс логику приложения на нем же. Тяжелые места выносить в С/C++, благо интегрировать сишный код с питоном проще простого.

                      Я не говорю, что то, что вы написали, не нужно. Я всего лишь хочу понять чем ваш подход лучше того, что я предложил, и ничего более.
                      • 0

                        Вот здесь вы найдете проект на Python + Tkinter со всеми исходниками GUI, включая проект. Посмотрите, сравните и ответьте на вопрос "я имел ввиду все тоже самое сделать на питоне через виджеты Ткинтера, красиво и чисто, плюс логику приложения на нем же".
                        Ну ни чем не отличается. Кому что нравится или на чем уже было сделаною

                        • 0
                          красиво и чисто

                          Если вы имеете ввиду отступы в блоках python-а, то да, он заставляет писать структурированно.

                          • 0
                            красиво и чисто

                            Оказывается спойлер убил всю красоту кода!

                    • +3
                      Можно взять и питон, но думаю, что статья тогда будет называться «Разработка приложений на языке Python с использованием Tkinter». В данной же статье описывается работа с Tcl/Tk именно из C/C++. Вполне полезная статья.
                      • 0
                        Ну я вроде бы и не говорил что она вредная. Но мне не очень ясен практический смысл. Код в статье просто вырвиглазный, а судя по самому процессу интеграции, поддерживать это будет очень сложно. Поэтому мной и был задан вопрос — зачем так сложно, если можно быстрее и проще с тем же результатом?
                        • 0

                          Так код-то генерируемый!

                      • 0
                        Tkinter тянет за собой tcl тогда какой смысл в питоне?
                        • +1

                          В разнообразии

                      • 0
                        Но зачем, когда есть тот же Qt?
                        • +1

                          Ну во первых, В начале было Слово, т.е. все Tcl/Tk.
                          Я программирую и на том и том и на третьем. Писать на Qt и на Tk это две большие разницы. Попробуйте и увидите насколько легко и просто интрегрировать C/C++ и с Tcl и с Tk.
                          А вопрос риторический, а зачем Фортран, а зачем Python, а зачем Ada, а зачем Perl и т.д.
                          Вы же наверное разные рубашки носите. Я обещал и в ближайшие дни выложу материал о том, как использовать динамические C-библиотеки использовать и Tcl.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое