Search code examples
perlunicodedrag-and-droptk-toolkit

Perl/Tk Dropsite: Dragging Windows files with arbitrary Unicode names


In a Perl/Tk app I want to drag & drop files with arbitrary unicode filenames onto a widget.

There is this working DropSite example: perl tk drag & drop folder from windows explorer but it doesn't work with filenames that contain unicode characters, e.g. cyrillic mixed with German. The special characters (that are not on the local codepage) are received just as "?".

Does anyone have a solution?


Solution

  • The Microsoft help page Ikegami mentioned, how to change the Windows code page, also shows how to change the code page for all of Windows (not just per app):

    go to Windows Settings > Time & language > Language & region > Administrative language settings > Change system locale, and check Beta: Use Unicode UTF-8 for worldwide language support. Then reboot the PC for the change to take effect.

    I did that and it worked fine for me and solved the DropSite problem too. (But you need to decode the received string to utf8.)

    So the modified version of the above mentioned working script would then be:

    use strict;
    use warnings;
    use Tk;
    use Tk::DropSite;
    use Encode;
    
    my $textVariable = "drag here";
    
    my $mw = MainWindow->new;
    
    my $frame = $mw->Frame(
    )->pack(-side => 'top', -expand => 1, -fill => 'x');
    
    $frame->Label(
        -text => "My Label",
        -anchor => 'w',
        -width => 10,
    )->pack(-ipady => 1, -side => 'left');
    
    my $entry = $frame->Entry(
        -textvariable => \$textVariable,
        -width => 40,
    )->pack(-side => 'left');
    
    $frame->DropSite(
        -dropcommand => [\&AcceptDrop, $frame],
        -droptypes => ('Win32'),
    );
    
    $mw->MainLoop;
    
    
    sub AcceptDrop {
        my ($widget, $selection) = @_;
        my $filename;
    
        $filename = decode_utf8 $widget->SelectionGet(
            -selection => $selection, 
            'STRING'
        );
        $textVariable = $filename;
    } # /AcceptDrop