{
   This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}
unit Ufrmmain;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, GR32_Layers,
  Dialogs, ComCtrls, ImgList, Menus, ExtCtrls,
  GR32, GR32_Image, GR32_transforms,
  UBrowserListView, StdCtrls,
  FreeBitmap, FreeImage, FreeUtils, ToolWin, Mask, CommCtrl,
  TB2Item, TB2Dock, TB2Toolbar,
  vistaaltfixunit, shlobj, comobj, ActiveX,
  BomeOneInstance, ShlIntf, ShellControls, ShellBrowser,
  Buttons, gifimage, GR32_Resamplers;

const
  thisapptitle = 'nView';
  thisregname = 'nSeries\nView';

type
  tprogrammode = (pmstartview, pmnostartview);
  taddresstype = (atnone, atfile, atfolder);

  TAccessComboBox = class(TCustomComboBox)
  end;

  Tfrmmain = class(TForm)
    pmbrowserlist: TPopupMenu;
    N1: TMenuItem;
    mnusorttype: TMenuItem;
    N3: TMenuItem;
    N4: TMenuItem;
    N5: TMenuItem;
    N6: TMenuItem;
    mnu_viewstyle1: TMenuItem;
    mnu_viewstyle3: TMenuItem;
    mnu_viewstyle4: TMenuItem;
    N7: TMenuItem;
    N8: TMenuItem;
    mnuthumbsize: TMenuItem;
    N1001: TMenuItem;
    N1101: TMenuItem;
    N1201: TMenuItem;
    mnuthumbsize1: TMenuItem;
    mnuthumbhigh: TMenuItem;
    N16: TMenuItem;
    mnudelete: TMenuItem;
    mnurefresh: TMenuItem;
    mnuthumbshowicon: TMenuItem;
    mnuthumbspace: TMenuItem;
    mnuthumbspace1: TMenuItem;
    N391: TMenuItem;
    N411: TMenuItem;
    N441: TMenuItem;
    N471: TMenuItem;
    N601: TMenuItem;
    imgview321: TImgView32;
    timerhidemessage: TTimer;
    N27: TMenuItem;
    N28: TMenuItem;
    mnunewfolder: TMenuItem;
    N17: TMenuItem;
    N29: TMenuItem;
    N30: TMenuItem;
    Splitter2: TSplitter;
    Splitter1: TSplitter;
    TBToolbar1: TTBToolbar;
    btnback: TTBSubmenuItem;
    btnforward: TTBSubmenuItem;
    bsSkinSpeedButton2: TTBItem;
    TBSubmenuItem2: TTBSubmenuItem;
    TBItem1: TTBItem;
    btnselectmode: TTBItem;
    btnmovemode: TTBItem;
    TBSubmenuItem1: TTBSubmenuItem;
    bsSkinSpeedButton1: TTBItem;
    bsSkinSpeedButton4: TTBItem;
    TBToolbar2: TTBToolbar;
    TBControlItem2: TTBControlItem;
    addressbox: TComboBox;
    StatusBar1: TStatusBar;
    ImageList1: TImageList;
    N31: TMenuItem;
    N32: TMenuItem;
    Panel1: TPanel;
    TBSubmenuItem3: TTBSubmenuItem;
    N34: TMenuItem;
    N35: TMenuItem;
    N36: TMenuItem;
    N37: TMenuItem;
    TBSubmenuItem5: TTBSubmenuItem;
    TBItem4: TTBItem;
    TBItem5: TTBItem;
    mnuratio0: TTBItem;
    TBItem6: TTBItem;
    N42: TMenuItem;
    N251: TMenuItem;
    N43: TMenuItem;
    bsSkinButton1: TTBSubmenuItem;
    TBItem7: TTBItem;
    N45: TMenuItem;
    ImageList2: TImageList;
    browsertimer: TTimer;
    N47: TMenuItem;
    N48: TMenuItem;
    N49: TMenuItem;
    N801: TMenuItem;
    N701: TMenuItem;
    N602: TMenuItem;
    N501: TMenuItem;
    N1501: TMenuItem;
    TBItem8: TTBItem;
    TBSubmenuItem6: TTBSubmenuItem;
    TBItem9: TTBItem;
    TBSeparatorItem1: TTBSeparatorItem;
    TBItem10: TTBItem;
    N50: TMenuItem;
    N51: TMenuItem;
    N52: TMenuItem;
    N53: TMenuItem;
    TBItem12: TTBItem;
    TBSeparatorItem3: TTBSeparatorItem;
    TBSeparatorItem2: TTBSeparatorItem;
    TBItem13: TTBItem;
    TBItem14: TTBItem;
    N54: TMenuItem;
    N55: TMenuItem;
    N56: TMenuItem;
    N46: TMenuItem;
    Shape1: TShape;
    TBItem15: TTBItem;
    Button1: TButton;
    TBItem16: TTBItem;
    TBSubmenuItem7: TTBSubmenuItem;
    mnunextimage: TTBItem;
    mnuprevimage: TTBItem;
    mnuend: TTBItem;
    mnuhome: TTBItem;
    N15: TTBSeparatorItem;
    mnumodechange: TTBItem;
    mnufullscreen: TTBItem;
    mnuvieweffect: TTBSubmenuItem;
    mnuvieweffect0: TTBItem;
    Fade1: TTBItem;
    N18: TTBItem;
    N19: TTBItem;
    N20: TTBItem;
    N21: TTBItem;
    N22: TTBItem;
    N23: TTBItem;
    N24: TTBItem;
    N25: TTBItem;
    N39: TTBSubmenuItem;
    N40: TTBItem;
    N41: TTBItem;
    N901: TTBItem;
    N1801: TTBItem;
    N2701: TTBItem;
    N26: TTBItem;
    N13: TTBSeparatorItem;
    mnuplus: TTBItem;
    mnuminus: TTBItem;
    N9: TTBSeparatorItem;
    mnucopyclipboard: TTBItem;
    N44: TTBItem;
    N33: TTBItem;
    N10: TTBSubmenuItem;
    mnuwindowsback: TTBItem;
    N12: TTBItem;
    N14: TTBItem;
    N38: TTBItem;
    N11: TTBSeparatorItem;
    mnusaveas: TTBItem;
    N2: TTBItem;
    mnuprint: TTBItem;
    TBSeparatorItem4: TTBSeparatorItem;
    panelgif: TPanel;
    N58: TMenuItem;
    TBItem2: TTBItem;
    TBItem3: TTBItem;
    N57: TMenuItem;
    TBItem18: TTBItem;
    loadingtimer: TTimer;
    N59: TMenuItem;
    TBItem11: TTBItem;
    TBSeparatorItem5: TTBSeparatorItem;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ListView1DblClick(Sender: TObject);
    procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn);
    procedure mnusorttypeClick(Sender: TObject);
    procedure mnu_viewstyle1Click(Sender: TObject);
    procedure imgview321MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    procedure ListView1SelectItem(Sender: TObject; Item: TListItem;
      Selected: Boolean);
    procedure imgview321MouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    procedure imgview321MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer; Layer: TCustomLayer);
    procedure imgview321MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    procedure N6Click(Sender: TObject);
    procedure N8Click(Sender: TObject);
    procedure mnuminusClick(Sender: TObject);
    procedure mnuplusClick(Sender: TObject);
    procedure mnunextimageClick(Sender: TObject);
    procedure mnuprevimageClick(Sender: TObject);
    procedure mnuhomeClick(Sender: TObject);
    procedure mnuendClick(Sender: TObject);
    procedure mnuwindowsbackClick(Sender: TObject);
    procedure btnselectmodeClick(Sender: TObject);
    procedure mnusaveasClick(Sender: TObject);
    procedure mnuprintClick(Sender: TObject);
    procedure mnumodechangeClick(Sender: TObject);
    procedure imgview321DblClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure mnuratio0Click(Sender: TObject);
    procedure mnufullscreenClick(Sender: TObject);
    procedure mnuthumbhighClick(Sender: TObject);
    procedure mnuthumbsize1Click(Sender: TObject);
    procedure mnuvieweffect0Click(Sender: TObject);
    procedure mnudeleteClick(Sender: TObject);
    procedure mnurefreshClick(Sender: TObject);
    procedure mnuthumbshowiconClick(Sender: TObject);
    procedure mnuthumbspace1Click(Sender: TObject);
    procedure treeview1Change(Sender: TObject; Node: TTreeNode);
    procedure treeview1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: controls.TDragState; var Accept: Boolean);
    procedure treeview1DragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure timerhidemessageTimer(Sender: TObject);
    procedure imgview321Resize(Sender: TObject);
    procedure bsSkinSpeedButton4Click(Sender: TObject);
    procedure btnbackClick(Sender: TObject);
    procedure imgview321MouseLeave(Sender: TObject);
    procedure mnunewfolderClick(Sender: TObject);
    procedure pmbrowserlistPopup(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure N17Click(Sender: TObject);
    procedure bsSkinSpeedButton1Click(Sender: TObject);
    procedure bsSkinSpeedButton2Click(Sender: TObject);
    procedure bsSkinButton1Click(Sender: TObject);
    procedure btnbackPopup(Sender: TTBCustomItem; FromLink: Boolean);
    procedure N31Click(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure TBItem3Click(Sender: TObject);
    procedure TBItem2Click(Sender: TObject);
    procedure N37Click(Sender: TObject);
    procedure N38Click(Sender: TObject);
    procedure TBItem5Click(Sender: TObject);
    procedure TBItem4Click(Sender: TObject);
    procedure N26Click(Sender: TObject);
    procedure N40Click(Sender: TObject);
    procedure TBItem6Click(Sender: TObject);
    procedure N42Click(Sender: TObject);
    procedure N43Click(Sender: TObject);
    procedure addressboxKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure TBItem7Click(Sender: TObject);
    procedure TBSubmenuItem5Popup(Sender: TTBCustomItem;
      FromLink: Boolean);
    procedure addressboxClick(Sender: TObject);
    procedure addressboxDropDown(Sender: TObject);
    procedure btnforwardPopup(Sender: TTBCustomItem; FromLink: Boolean);
    procedure N44Click(Sender: TObject);
    procedure N45Click(Sender: TObject);
    procedure TBSubmenuItem1Popup(Sender: TTBCustomItem;
      FromLink: Boolean);
    procedure browsertimerTimer(Sender: TObject);
    procedure N48Click(Sender: TObject);
    procedure TBItem8Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure TBItem9Click(Sender: TObject);
    procedure TBSubmenuItem6Popup(Sender: TTBCustomItem;FromLink: Boolean);
    procedure TBItem10Click(Sender: TObject);
    procedure N51Click(Sender: TObject);
    procedure N53Click(Sender: TObject);
    procedure TBItem12Click(Sender: TObject);
    procedure N55Click(Sender: TObject);
    procedure TBItem15Click(Sender: TObject);
    procedure TBItem16Click(Sender: TObject);
    procedure TBSubmenuItem7Popup(Sender: TTBCustomItem;
      FromLink: Boolean);
    procedure TBToolbar1ShortCut(var Msg: TWMKey; var Handled: Boolean);
    procedure N58Click(Sender: TObject);
    procedure mnucopyclipboardClick(Sender: TObject);
    procedure N57Click(Sender: TObject);
    procedure TBItem18Click(Sender: TObject);
    procedure loadingtimerTimer(Sender: TObject);
    procedure N59Click(Sender: TObject);
  private
    { Private declarations }
    programmode:tprogrammode;
    startviewlist:tlist;
    startviewindex:integer;

    OldMousePos: TPoint;
    MouseDragging: Boolean;
    xorg,yorg,xmov,ymov:integer;
    RBLayerSelect:TRubberbandLayer;
    selectionenabled:boolean;
    form1:TForm; //fullscreen
    imgmoveblock: boolean;

    //preview
    preview:TBitmapLayer;
    previewselect:TRubberBandLayer;
    previewposition:TPositionedLayer;
    previewscale:single;
    previewmousedown:boolean;

    messagelayer:TBitmapLayer;
    beforeviewcheck:boolean;

    OldWndProc,NewWndProc:pointer;
    browserpath:string;
    Fkillfocus:boolean;
    findword:string;
    findindex:integer;

    gifimage:timage;
    gif:Tgifimage;
    vistaaltfixonidle:TIdleEvent;

    FpanelWndProc: TWndMethod;
    dblclicked:boolean;
    fitchanged:boolean;
    loadingtime:cardinal;

    procedure HookWndProc(var Message: TMessage);
    procedure PanelWndProc(var Message: TMessage);
    procedure BrowserListView1OnBrowserEnded(sender:tobject);
    procedure BrowserListView1OnBrowserbefore(sender:tobject;path:string);
    procedure BrowserListView1OnInsertEnd(sender:tobject);
    function convertabsolutepos(x,y:integer):TPoint;
    procedure DrawTheRect;
    procedure Select(R:Trect);
    procedure modechange(viewmode:boolean);
    procedure startviewcheck(param:string;isfirststart:boolean);
    procedure clear_startviewlist();
    procedure loadfile(name:string;data:PThumbImage=nil);
    procedure listview1move(idx:integer);

    procedure WndProc(var Message: TMessage); override;
    procedure set_config;
    procedure form1Close(Sender: TObject; var Action: TCloseAction);
    procedure applicationOnShortCut(var Msg: TWMKey; var Handled: Boolean);
    function decode_address(s:string):taddresstype;
    procedure checkfolder(path:string);
    procedure displaymessage(s:string);
    function parsepath(s:string):boolean;
    procedure navigateonchange(Sender: TObject);
    procedure navigateonclick(Sender: TObject);
    procedure treeview1setpath(path:string);
    procedure applicationOnMessage(var Msg: tagMSG; var Handled: Boolean);
    function get_toolbarpopupPos(toolbar:ttbtoolbar; item:TTBCustomItem): tpoint;
    procedure applicationOnIdle(Sender: TObject; var Done: Boolean);
    procedure fittoscreen();
    procedure createrationmenu();

    procedure setpreview;
    procedure setpreviewselect;
    procedure setpreviewselect2;
    procedure setpreviewresize;
    procedure previewpositionPaint(Sender: TObject; Buffer: TBitmap32);
    procedure previewselectResizing(Sender: TObject;
       const OldLocation: TFloatRect; var NewLocation: TFloatRect;
       DragState: TDragState; Shift: TShiftState);
    procedure OneInstance1InstanceStarted(Sender: TObject; params: TStringList);
    procedure proc_movefile(dest:string);
    function test_movefile(dest:string):boolean;
    procedure listview1DragOver(Sender, Source: TObject; X,Y:  Integer; State: controls.TDragState; var Accept: Boolean);
    procedure listview1DragDrop(Sender, Source: TObject; X,Y: Integer);
    procedure listview1OnEditing(Sender: TObject; Item: TListItem;var AllowEdit: Boolean);
    procedure favoriteOnClick(Sender: TObject);
    procedure proc_find();
    procedure load_gifaniimage(filename:string);
    procedure set_gifposition();
    procedure gifimageOnClick(Sender: TObject);
    procedure proc_timer(Message:TMessage);
    procedure Deselectall();
    procedure treeview1OnAddFolder(Node: TTreeNode; Path: String; var CanAdd: Boolean);
    procedure ShowSystemError(msg:string);
    procedure setimgview321Cursor(Cursor:TCursor);
  public
    { Public declarations }
    treeview1: TJamShellTree;
    listview1:Tmylistview;
    BrowserListView1:TBrowserListView;
  end;

var
  frmmain: Tfrmmain;
  OneInstance:TOneInstance;

  currentimage:PThumbImage;
  currentpath:string;

implementation

uses Ufunction, Uconfig, Registry, ShellApi, UfrmPrint,
  im_Clipboard, Ufrmworkselect, Uregistry,
  Ufrmresize, UfrmOption, Umainhelper, clipbrd, Ufrmabout, Ufrmrename, Ufrmfavadd,
  Ufrmgif, Ufrmfav, Ufrmratio, Uupdate, Udialog, Ufrmsaveopt;

{$R *.dfm}

procedure Tfrmmain.FormCreate(Sender: TObject);
var
  i:integer;
  SmallImagesHandle,LargeImagesHandle:HImageList;
begin
  updatefilecheck;
  OneInstance.OnInstanceStarted:=OneInstance1InstanceStarted;

  TVistaAltFix.Create(Self);
  sysutils.ForceDirectories(GetAppDirectory);

  self.Caption:=format('nView - 이미지,사진보기 그리고 이미지 편집,효과주기 (%s)',[GetVersion(paramstr(0))]);
  load_strcmplogical;

  fileimagelist:=TImageList.Create(nil);
  SmallImagesHandle := GetSystemImageList(False);
  fileimagelist.Handle:=SmallImagesHandle;
  fileimagelist.ShareImages:=true;
  fileimagelist2:=TImageList.Create(nil);
  LargeImagesHandle := GetSystemImageList(true);
  fileimagelist2.Handle:=LargeImagesHandle;
  fileimagelist2.ShareImages:=true;

  New(currentimage);
  config.LoadFromFile(GetAppDirectory+'config.ini');

  if config.selectmode then btnselectmode.Checked:=true
  else btnmovemode.Checked:=true;

  sortcolumn:=config.sortcolumn;
  for i:=Low(sortreverseorder) to High(sortreverseorder) do
		sortreverseorder[i]:=False;
  sortreverseorder[sortcolumn]:=config.sortreverseorder;

  if config.lastpath='' then config.lastpath:='c:\';
  if config.lastdir='' then config.lastdir:=GetAppDirectory2;
  self.Left:=config.window_left;
  self.Top:=config.window_top;
  self.Width:=config.window_width;
  self.Height:=config.window_height;

  if config.window_max then
    self.WindowState:=wsMaximized;

  listview1:=Tmylistview.Create(self);
  listview1.Parent:=self;
  listview1.BorderStyle:=bsnone;
  listview1.DragMode:=dmAutomatic;
  listview1.HideSelection:=false;
  listview1.ReadOnly:=false;
  listview1.RowSelect:=true;
  listview1.MultiSelect:=true;
  listview1.Align:=alright;
  listview1.Width:=config.listview1width;
  listview1.TabStop:=true;  
  listview1.PopupMenu:=pmbrowserlist;
  listview1.OnSelectItem:=ListView1SelectItem;
  listview1.OnDblClick:=ListView1DblClick;
  listview1.OnColumnClick:=ListView1ColumnClick;
  listview1.OnDragOver:=listview1DragOver;
  listview1.OnDragDrop:=listview1DragDrop;
  listview1.OnEditing:=listview1OnEditing;
  Splitter2.Align:=alright;

  imgview321.Align:=alclient;

  Screen.Cursors[10]:=LoadCursor(HInstance, 'MAGNIFY');
  //LoadCursorFromFile(pchar(GetAppDirectory+'MAGNIFY.CUR'));

  BrowserListView1:=TBrowserListView.Create(listview1);
  BrowserListView1.ExImageList:=ImageList1;
  listview1.Columns.Items[0].Width:=config.listview1colwidth;
  BrowserListView1.setviewstyle(Tviewstyle(config.viewstyle));
  BrowserListView1.OnBrowserEnded:=BrowserListView1OnBrowserEnded;
  BrowserListView1.OnBrowserbefore:=BrowserListView1OnBrowserbefore;
  BrowserListView1.OnInsertEnd:=BrowserListView1OnInsertEnd;

  if (config.thumbsize<50) or (config.thumbsize>150) then
    config.thumbsize:=100;
  BrowserListView1.Setthumbsize(config.thumbsize);
  if (config.thumbspace<20) or (config.thumbspace>60) then
    config.thumbspace:=30;
  BrowserListView1.Setthumbspace(config.thumbspace);

  application.OnShortCut:=applicationOnShortCut;

  vistaaltfixonidle:=application.OnIdle;
  application.OnIdle:=applicationOnIdle;

  sysutils.ForceDirectories(GetAppDirectory+'cache');

  if sysutils.FileExists(GetAppDirectory+'history.dat') then
    addressbox.Items.LoadFromFile(GetAppDirectory+'history.dat');

  {$ifdef release}
  {$endif}

//  application.OnMessage:=applicationOnMessage;

  messagelayer:=TBitmapLayer.Create(imgview321.Layers);

  OldWndProc:=Pointer(GetWindowLong(TAccessComboBox(addressbox).EditHandle, GWL_WNDPROC));
  NewWndProc:=MakeObjectInstance(HookWndProc);
  SetWindowLong(TAccessComboBox(addressbox).EditHandle, GWL_WNDPROC, LongInt(NewWndProc));

  FpanelWndProc := panelgif.WindowProc;
  panelgif.WindowProc := PanelWndProc;

  favorite:=Tfavorite.Create;
  createrationmenu();
  imgcache:=Timgcache.Create;

  TBToolbar1.processshortcutHandled:=true;
  set_config;
end;

procedure Tfrmmain.createrationmenu();
var
  i:integer;
  item:TTBCustomItem;
begin
  for i:=1 to 9 do begin
    item:=TTBCustomItem.Create(self);
    item.Caption:=format('%d%%',[i*10]);
    item.Tag:=0;
    item.GroupIndex:=1;
    item.OnClick:=mnuratio0Click;
    TBSubmenuItem1.Add(item);
  end;
  for i:=1 to 10 do begin
    item:=TTBCustomItem.Create(self);
    item.Caption:=format('%d%%',[i*100]);
    item.Tag:=0;
    item.GroupIndex:=1;
    item.OnClick:=mnuratio0Click;
    if i=1 then item.ShortCut:=texttoshortcut('shift+1');
    TBSubmenuItem1.Add(item);
  end;
end;

procedure Tfrmmain.FormShow(Sender: TObject);
var
  Options: DWORD;
  pac2:IAutoComplete2;
  Dummy:IUnknown;
  Strings:IEnumString;
  pac:IAutoComplete;
begin
  beforeviewcheck:=true;
  startviewcheck(paramstr(1),true);
  beforeviewcheck:=false;

  //shell autocomplete
  Dummy:=CreateComObject(CLSID_AutoComplete);
  if (Dummy <> nil) and (Dummy.QueryInterface(IID_IAutoComplete, pac) = S_OK) then begin
     Strings:=CreateComObject(CLSID_ACListISF) as IEnumString;

    if pac.Init(TAccessComboBox(self.addressbox).EditHandle, Strings, nil, nil) = S_OK then
      if pac.QueryInterface(IID_IAutoComplete2, pac2)=s_ok then begin
        pac.Enable(true);
        pac2.SetOptions(ACO_AUTOSUGGEST or ACO_USETAB); //ACO_UPDOWNKEYDROPSLIST
      end;
  end;
end;

procedure Tfrmmain.FormDestroy(Sender: TObject);
begin
  if WindowState=wsNormal then begin
    config.window_left:=self.Left;
    config.window_top:=self.Top;
    config.window_width:=self.Width;
    config.window_height:=self.Height;
    config.window_max:=false;
  end else if WindowState=wsMaximized then
    config.window_max:=true;

  if listview1.Width>5 then
    config.listview1width:=listview1.Width;
  if (treeview1<>nil) then begin
    if (treeview1.Width>5) then
      config.ShellTree1width:=treeview1.Width;
  end;
  config.listview1colwidth:=listview1.Columns.Items[0].Width;

  config.sortcolumn:=sortcolumn;
  config.sortreverseorder:=sortreverseorder[sortcolumn];
  config.selectmode:=btnselectmode.Checked;
  config.viewstyle:=integer(listview1.ViewStyle);

  config.SaveToFile(GetAppDirectory+'config.ini');

  addressbox.Items.SaveToFile(GetAppDirectory+'history.dat');

  BrowserListView1.Free;
  dispose(currentimage);
  fileimagelist.Free;
  fileimagelist2.Free;
  messagelayer.Free;

  favorite.Free;
  freeandnil(navigate);
  freeandnil(gifimage);
  freeandnil(gif);
  imgcache.Free;

  checkupdate();
end;

function Tfrmmain.decode_address(s:string):taddresstype;
begin
  if sysutils.DirectoryExists(s) then
    result:=atfolder
  else if sysutils.FileExists(s) then
    result:=atfile
  else
    result:=atnone;
end;

procedure Tfrmmain.clear_startviewlist();
var
  i:integer;
begin
  for i:=0 to startviewlist.Count-1 do
    dispose(PThumbImage(startviewlist.Items[i]));
  startviewlist.Clear;
end;

procedure Tfrmmain.startviewcheck(param:string;isfirststart:boolean);
var
  s,path,exts:string;
  i:integer;
  at:taddresstype;
  PThumbImage1:PThumbImage;

  FHandle:THandle;
  fd:WIN32_FIND_DATA;
  size:int64;
  LocalFileTime:TFileTime;
begin
  s:=param;
  s:=trim(s);

    at:=decode_address(s);
    if (at=atnone) and DirectoryExists(ExtractFilePath(s)) then begin
      at:=atfolder;
      s:=ExtractFilePath(s);
    end;

    case at of
      atfile:begin
        programmode:=pmstartview;
        if startviewlist=nil then
          startviewlist:=tlist.Create
        else
          clear_startviewlist();
        path:=ExtractFilePath(s);
        checkfolder(path);

        if issystemfolder(path)=false then begin
          exts:=lowercase(FIU_GetFullExtList)+';';
          FHandle:= Windows.FindFirstFile(PChar(path+'*.*'), FD);
          if FHandle <> INVALID_HANDLE_VALUE then
            repeat
             if ((fd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)=0) and ((fd.dwFileAttributes and FILE_ATTRIBUTE_SYSTEM)=0) and
               ( g_showhidden or config.c_showhidden or ((config.c_showhidden=false) and ((fd.dwFileAttributes and FILE_ATTRIBUTE_HIDDEN)=0)) ) then begin
              if pos('*'+lowercase(ExtractFileExt(fd.cFileName))+';',exts)>0 then begin
                new(PThumbImage1);
                PThumbImage1.bitmap:=nil;
                PThumbImage1.imagetype:=itfile;
                PThumbImage1.name:=path + fd.cFileName;
                PThumbImage1.attrs:=fd.dwFileAttributes;
                FileTimeToLocalFileTime(fd.ftLastWriteTime, LocalFileTime);
                if FileTimeToDosDateTime(LocalFileTime, LongRec(PThumbImage1.time).Hi, LongRec(PThumbImage1.time).Lo)=false then
                  PThumbImage1.time:=-1;
                size := FD.nFileSizeHigh;
                size := size shl 32;
                size := size + FD.nFileSizeLow;
                PThumbImage1.size:=size;
                startviewlist.Add(PThumbImage1);
              end;
             end;
            Until Not Windows.FindNextFile(FHandle, FD);
          Windows.FindClose(FHandle);
        end;

           if startviewlist.Count=0 then begin
             FHandle:= Windows.FindFirstFile(PChar(s), FD);
             if FHandle <> INVALID_HANDLE_VALUE then begin
                new(PThumbImage1);
                PThumbImage1.bitmap:=nil;
                PThumbImage1.imagetype:=itfile;
                PThumbImage1.name:=path + fd.cFileName;
                PThumbImage1.attrs:=fd.dwFileAttributes;
                FileTimeToLocalFileTime(fd.ftLastWriteTime, LocalFileTime);
                if FileTimeToDosDateTime(LocalFileTime, LongRec(PThumbImage1.time).Hi, LongRec(PThumbImage1.time).Lo)=false then
                  PThumbImage1.time:=-1;
                size := FD.nFileSizeHigh;
                size := size shl 32;
                size := size + FD.nFileSizeLow;
                PThumbImage1.size:=size;
                startviewlist.Add(PThumbImage1);
             end;
             Windows.FindClose(FHandle);
           end;

        startviewlist.Sort(AddlistSortProc);
        startviewindex:=0;
        for i:=0 to startviewlist.Count-1 do
          if comparetext(PThumbImage(startviewlist.Items[i]).name,s)=0 then begin
            startviewindex:=i;
            break;
          end;
        modechange(true);
        loadfile(s);
      end;
      atfolder:begin
        programmode:=pmnostartview;
        modechange(false);
        if isfirststart then begin
          browserpath:=s;
          browsertimer.Enabled:=true
        end else
          treeview1setpath(s);
      end;
      else
         programmode:=pmnostartview;
         modechange(false);
         if isfirststart then begin
           browserpath:=config.lastpath;
           browsertimer.Enabled:=true;
         end else
           treeview1setpath(config.lastpath);
    end;
end;

procedure Tfrmmain.treeview1setpath(path:string);
var
  strlist:tstringlist;
  s,s2:string;
  i,j:integer;
  rootnode:ttreenode;
  finded:boolean;

  function find(depth:integer;node:ttreenode):boolean;
  var
    i:integer;
    s:string;
  begin
    result:=false;
    if depth>strlist.Count-1 then begin
      result:=true;
      node.Selected:=true;
      exit;
    end;
    node.Expand(false);
    for i:=0 to node.Count-1 do begin
      s:=treeview1.GetFullPath(node.Item[i]);
      if (length(s)>0) and (s[length(s)]='\') then delete(s,length(s),1);
      s:=sysutils.ExtractFileName(s);
      if comparetext(s,strlist.Strings[depth])=0 then begin
        result:=find(depth+1,node.Item[i]);
      end;
    end;
  end;
begin
  if sysutils.DirectoryExists(path)=false then begin
    MessageDlg('폴더가 존재하지 않습니다.',mterror, [mbOk], 0);
    exit;
  end;

  checkfolder(path);
  if comparetext(treeview1.SelectedFolder,path)=0 then
    BrowserListView1.BrowserDirectory(treeview1.SelectedFolder)
  else begin
    s:=path;
    s:=lowercase(s);
    if (length(s)>0) and (s[length(s)]<>'\') then s:=s+'\';

    finded:=false;
    rootnode := treeview1.Items.GetFirstNode;
    if rootnode<>nil then begin
      for i:=0 to rootnode.Count-1 do begin
        s2:=treeview1.GetFullPath(rootnode.Item[i]);
        if (length(s2)>0) and (s2[length(s2)]<>'\') then s2:=s2+'\';
        s2:=lowercase(s2);
//        if (s2='') or (s2='c:\') then begin
        if (s2='c:\') then begin
          break;
        end;
        if pos(s2,s)=1 then begin
          s:=sysutils.StringReplace(s,s2,'',[]);
          strlist:=tstringlist.Create;
          try
            SplitString(s,strlist,'\');
            finded:=find(0,rootnode.Item[i]);
          finally
            strlist.Free;
          end;
          break;
        end;
      end;
    end;

    if finded=false then
      treeview1.SelectedFolder:=path;
  end;

end;

procedure Tfrmmain.treeview1OnAddFolder(Node: TTreeNode; Path: String; var CanAdd: Boolean);
begin
  canadd:=Path<>'';
  if canadd and (UpperCase(ExtractFileExt(Path))='.ZIP') and (DirectoryExists(path)=false) then
    canadd:=false;
  if (canadd=false) and IsNetworkPidl(TJamShellTreeItem(node.data).AbsolutePIDL) then
    canadd:=true;
end;

procedure Tfrmmain.modechange(viewmode:boolean);
var
  i:integer;
begin
  if viewmode then begin
    Splitter1.Visible:=false;
    Splitter2.Visible:=false;
    listview1.Visible:=false;
    if treeview1<>nil then
      treeview1.Visible:=false;
    TBToolbar2.Visible:=false;
    imgview321.Color:=config.c_viewcolor;
    try
      imgview321.SetFocus;
    except
    end;
  end else begin
    if treeview1=nil then begin
      treeview1:=TJamShellTree.Create(self);
      treeview1.Parent:=self;
      treeview1.Width:=config.ShellTree1width;
      treeview1.Left:=-1*treeview1.Width;
      treeview1.Align:=alleft;
      treeview1.RootedAtNoExpand:=false;
      treeview1.RootedAt:=SF_DESKTOP;
      treeview1.OnAddFolder:=treeview1OnAddFolder;
//      treeview1.Root:='rfMyComputer';
      treeview1.ShowRoot:=false;
      if config.c_showhidden or g_showhidden then
        treeview1.ShowOptions:=treeview1.ShowOptions+[soShowHidden]
      else
        treeview1.ShowOptions:=treeview1.ShowOptions-[soShowHidden];
      treeview1.ShowOptions:=treeview1.ShowOptions-[soShowRecycleBin];
//      treeview1.ObjectTypes:=[otFolders,otHidden];
//      treeview1.UseShellImages:=true;
      treeview1.RightClickSelect:=true;
      treeview1.HideSelection:=false;
//      treeview1.AutoRefresh:=true;
      treeview1.OnChange:=treeview1Change;
      treeview1.OnDragOver:=treeview1DragOver;
      treeview1.OnDragDrop:=treeview1DragDrop;
      Splitter1.Align:=alleft;

      if navigate=nil then
        navigate:=Tnavigate.Create;
      navigate.onchange:=navigateonchange;
    end;

    if programmode=pmstartview then begin
      programmode:=pmnostartview;
      if startviewlist.Count>0 then
        treeview1setpath(ExtractFilePath(PThumbImage(startviewlist.Items[0]).name))
      else
        treeview1setpath(config.lastpath);
      clear_startviewlist();
      freeandnil(startviewlist);
    end;
    ListView1.DoubleBuffered:=false;
    listview1.Visible:=true;
    treeview1.Visible:=true;
    Splitter1.Left:=treeview1.Left+treeview1.Width+50;
    Splitter1.Visible:=true;
    Splitter2.Left:=listview1.Left-50;
    Splitter2.Visible:=true;
    TBToolbar2.Visible:=true;
    FormResize(nil);
    imgview321.Color:=config.c_defaultviewcolor;//$00DAD0CD;
    if listview1.Selected<>nil then begin
      listview1.Selected.MakeVisible(false);
      BrowserListView1.updatethumb;
    end;
  end;
end;

procedure Tfrmmain.ListView1ColumnClick(Sender: TObject; Column: TListColumn);
begin
  case Column.Index of
    0:sortcolumn:=0;
    1:sortcolumn:=2;
    2:sortcolumn:=3;
    3:sortcolumn:=4;
    else
      exit;
  end;
  sortreverseorder[sortcolumn]:=not sortreverseorder[sortcolumn];
  BrowserListView1.sort;
  BrowserListView1.updatethumb;
end;

procedure Tfrmmain.ListView1DblClick(Sender: TObject);
var
  PThumbImage1:PThumbImage;
begin
  if ListView1.SelCount <= 0 then exit;
  PThumbImage1:=ListView1.Selected.Data;
  case PThumbImage1.imagetype of
    itfolder:
      if sysutils.ExtractFileName(PThumbImage1.name)='..' then begin
        if treeview1.Selected.Parent<>nil then
          treeview1.Selected.Parent.Selected:=true;
      end else
        treeview1setpath(PThumbImage1.name);
    else
      loadfile(PThumbImage1.name,PThumbImage1);
      modechange(listview1.Visible);
  end;
end;

procedure Tfrmmain.BrowserListView1OnBrowserbefore(sender:tobject;path:string);
begin
  Screen.Cursor:=crHourGlass;
  loadingtime:=gettickcount;
  loadingtimer.Enabled:=true;

  currentpath:=path;
  addressbox.Text:=path;
  navigate.addnavigate(path);
  if (listview1.Visible=false) then
    modechange(false);
end;

procedure Tfrmmain.BrowserListView1OnInsertEnd(sender:tobject);
begin
  if ListView1.Items.Count>0 then begin
    ListView1.Items[0].Selected:=true;
    listview1.Items[0].MakeVisible(true);
  end;
  BrowserListView1.sort;
  BrowserListView1.updatethumb;

  loadingtimer.Enabled:=false;
  timerhidemessageTimer(nil);
  Screen.Cursor:=crdefault;
end;

procedure Tfrmmain.BrowserListView1OnBrowserEnded(sender:tobject);
begin
  loadingtimer.Enabled:=false;
  timerhidemessageTimer(nil);
  Screen.Cursor:=crdefault;
end;

procedure Tfrmmain.mnusorttypeClick(Sender: TObject);
begin
  case (sender as tmenuitem).Tag of
    1,2:begin
      sortcolumn:=0;
      sortreverseorder[0]:=(sender as tmenuitem).Tag = 2;
    end;
    3,4:begin
      sortcolumn:=2;
      sortreverseorder[2]:=(sender as tmenuitem).Tag = 4;
    end;
    5,6:begin
      sortcolumn:=3;
      sortreverseorder[3]:=(sender as tmenuitem).Tag = 6;
    end;
    7,8:begin
      sortcolumn:=4;
      sortreverseorder[4]:=(sender as tmenuitem).Tag = 8;
    end;
  end;
  BrowserListView1.sort;
  BrowserListView1.updatethumb;
end;

procedure Tfrmmain.mnu_viewstyle1Click(Sender: TObject);
begin
  case (Sender as TmenuItem).Tag of
    1:BrowserListView1.setviewstyle(vsicon);
    3:BrowserListView1.setviewstyle(vsList);
    4:BrowserListView1.setviewstyle(vsReport);
  end;
end;

function Tfrmmain.convertabsolutepos(x,y:integer):TPoint;
var
  np1:tpoint;
begin
  np1.X:=x;
  np1.y:=y;
  result:=imgview321.ControlToBitmap(np1);
end;

procedure Tfrmmain.loadfile(name:string;data:PThumbImage=nil);
var
  FBitmap: TFreeWinBitmap;
  bitmap: Tbitmap;
  t:cardinal;
  desc:string;

  ft,i,numero,rx,ry:integer;
  b,b1:tbitmap32;

  fif:FREE_IMAGE_FORMAT;
  mbitmap:TFreeMultiBitmap;
  isgif:boolean;

  FreeMemoryIO1:TFreeMemoryIO;
  stream:tmemorystream;
  pdata:PByte;
  SizeInBytes: DWORD;
  cachedata:Pcachedata;
  flag:boolean;
label cacheopened;
begin
  Screen.Cursor:=crHourGlass;
  if (data=nil) or (programmode=pmstartview) then currentimage.name:='';
  messagelayer.Visible:=false;
  t:=gettickcount;
  isgif:=false;
  FBitmap:=TFreeWinBitmap.Create;
  try try
    ft:=FileAge(name);
    if ft<>-1 then begin
      cachedata:=imgcache.findcache(name,ft);
      if cachedata<>nil then begin
        imgview321.Bitmap.DrawMode:=dmblend;
        cachedata.stream.Position:=0;
        imgview321.Bitmap.LoadFromStream(cachedata.stream);
        isgif:=cachedata.isgif;
        if isgif then
          load_gifaniimage(name);
        goto cacheopened;
      end;
      if FBitmap.Load2(name,fif)=false then begin
        imgview321.Bitmap.Delete;
        displaymessage(format('%s 파일을 읽을 수 없습니다.',[ExtractFileName(name)]));
        exit;
      end else begin
        if fif=FIF_GIF then begin
          mbitmap:=TFreeMultiBitmap.Create();
          try
            mbitmap.Open2(name,fif,false,true);
            if mbitmap.GetPageCount>1 then begin
              isgif:=true;
              load_gifaniimage(name);
            end;
          finally
            mbitmap.Free;
          end;
        end;
      end;
    end else begin
      imgview321.Bitmap.Delete;
      displaymessage(format('%s 파일이 없습니다.',[ExtractFileName(name)]));
      exit;
    end;

    FreeMemoryIO1:=TFreeMemoryIO.Create();
    try
      FBitmap.SaveToMemory(FIF_BMP,FreeMemoryIO1);
      FreeMemoryIO1.Acquire(pdata,SizeInBytes);
      flag:=false;
      stream:=tmemorystream.Create;
      try
        stream.Write(pdata^,SizeInBytes);
        stream.Position:=0;
        imgview321.Bitmap.DrawMode:=dmblend;
        imgview321.Bitmap.LoadFromStream(stream);
        if config.c_cacheenable2 then begin
          new(cachedata);
          cachedata.filename:=name;
          cachedata.stream:=stream;
          cachedata.fileage:=ft;
          cachedata.isgif:=isgif;
          flag:=true;
          imgcache.addcache(cachedata);
        end;
      finally
        if flag=false then stream.Free;
      end;
    finally
      FreeMemoryIO1.Free;
    end;

cacheopened:
    if isgif=false then begin
      panelgif.Visible:=false;
      freeandnil(gifimage);
      freeandnil(gif);
    end;
    StatusBar1.Panels[0].Text:=ExtractFileName(name);

    if (data<>nil) then desc:=data.desc;
    if (desc='') and (cachedata<>nil) then desc:=cachedata.desc;
    if desc='' then begin
      if FBitmap.IsValid then begin
        desc:=format('(%d x %d) %d bit (%s)',[imgview321.Bitmap.Width,imgview321.Bitmap.Height,
               FBitmap.GetBitsPerPixel,trim(FreeImage_GetFIFDescription(fif))]);
        if (data<>nil) then data.desc:=desc;
        if (cachedata<>nil) then cachedata.desc:=desc;
      end else
        desc:=format('(%d x %d)',[imgview321.Bitmap.Width,imgview321.Bitmap.Height]);
    end;

    if config.ratio=0 then
      fittoscreen()
    else
      imgview321.Scale:=config.ratio / 100;

    t:=gettickcount-t;
    if RBLayerSelect<>nil then FreeAndNil(RBLayerSelect);

    if (config.c_vieweffectspeed<0) or (config.c_vieweffectspeed>1000) then
      config.c_vieweffectspeed:=25;

    if (listview1.Visible and (form1=nil)) or (beforeviewcheck) or (config.vieweffect=0) then begin
      imgview321.Changed;
    end else if config.vieweffect=1 then begin
      imgmoveblock:=true;
      imgview321.Bitmap.ResetAlpha;
      numero:=6;
      for i:=numero to 10 do begin
        if i=10 then
          imgview321.Bitmap.MasterAlpha := 255
        else
          imgview321.Bitmap.MasterAlpha := i*25;
        sleep(config.c_vieweffectspeed);
        application.ProcessMessages;
      end;
    end else begin
      imgmoveblock:=true;
      b:=tbitmap32.Create;
      b1:=tbitmap32.Create;
      b.Assign(imgview321.Bitmap);
      try
        numero:=5;
        if b.Width*b.Height > 150000 then numero:=numero-2;
        case config.vieweffect of
          2:begin rx:=-1; ry:=-1; end;
          3:begin rx:=-1; ry:=1; end;
          4:begin rx:=1; ry:=-1; end;
          5:begin rx:=1; ry:=1; end;
          6:begin rx:=0; ry:=-1; end;
          7:begin rx:=0; ry:=1; end;
          8:begin rx:=-1; ry:=0; end;
          9:begin rx:=1; ry:=0; end;
        end;
        for i:=numero downto 0 do begin
          b1.Assign(b);
          b1.Roll(rx*i*(b1.Width div numero),
             ry*i*(b1.Height div numero),
             true, Color32(imgview321.Color));
          sleep(config.c_vieweffectspeed);
          imgview321.Bitmap.Assign(b1);
          application.ProcessMessages;
        end;
      finally
        b.Free;
        b1.Free;
      end;
    end;

    StatusBar1.Panels[1].Text:=format('%s',[desc]);
    StatusBar1.Panels[2].Text:=format('로딩: %6.3f초',[t/1000]);
    if config.c_thumbpreview then
      setpreview;
   except
   end;
  finally
    if (data=nil) or (programmode=pmstartview) then begin
      currentimage.imagetype:=itfile;
      currentimage.name:=name;
      currentimage.istrans:=FBitmap.IsTransparent;
    end;
    FBitmap.Free;
    Screen.Cursor:=crDefault;
    imgmoveblock:=false;
  end;
end;

procedure Tfrmmain.ListView1SelectItem(Sender: TObject; Item: TListItem;
  Selected: Boolean);
var
  PThumbImage1:PThumbImage;
begin
  if Selected=false then exit;
  if listview1.SelCount>1 then exit;
{  if imgmoveblock then begin
    Item.Selected:=false;
    exit;
  end;}
  PThumbImage1:=PThumbImage(Item.Data);
  if PThumbImage1.imagetype=itfolder then exit;
  currentimage^:=PThumbImage1^;
  loadfile(PThumbImage1.name,PThumbImage1);
end;

procedure Tfrmmain.imgview321MouseWheel(Sender: TObject;
  Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
  var Handled: Boolean);
begin
  if WheelDelta >= 0 then begin
    mnuprevimageClick(nil);
  end else begin
    mnunextimageClick(nil);
  end;
  Handled := True;
end;

procedure Tfrmmain.imgview321MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer;
  Layer: TCustomLayer);
var
  np2:tpoint;
  rect1:trect;
  ratio:single;
begin
  if dblclicked then exit;
  if Button=mbRight then exit;

  if btnselectmode.Checked then begin
    np2:=convertabsolutepos(x,y);
    if RBLayerSelect<>nil then begin
      rect1:=MakeRect(RBLayerSelect.Location, rrInside);
      if windows.PtInRect(rect1,np2) then begin
        ratio:=(imgview321.Width / (rect1.Right-rect1.Left));
        imgview321.Scale:=ratio;
        imgview321.ScrollToCenter((rect1.Left+rect1.Right) div 2, (rect1.Top+rect1.Bottom) div 2);
        setimgview321Cursor(crDefault);
        FreeAndNil(RBLayerSelect);
        setpreviewselect;
        exit;
      end;
    end;
  end;

  if (previewposition<>nil) and (previewposition.Visible) then begin
    rect1:=MakeRect(previewposition.Location, rrInside);
    previewmousedown:=windows.PtInRect(rect1,point(x,y));
  end else
    previewmousedown:=false;

  if (preview<>nil) and (preview.Visible) then begin
    rect1:=MakeRect(preview.Location);
    if windows.PtInRect(rect1,point(x,y)) then
      exit;
  end;

  if RBLayerSelect<>nil then FreeAndNil(RBLayerSelect);

  if btnselectmode.Checked then begin
    Xorg:=np2.X; Yorg:=np2.y;
    Xmov:=np2.X; Ymov:=np2.y;
    selectionenabled:=true;
  end else begin
    OldMousePos := Point(X, Y);
    MouseDragging := True;
    setimgview321Cursor(crSizeAll);
  end;
end;

procedure Tfrmmain.imgview321MouseLeave(Sender: TObject);
begin
  setimgview321Cursor(crDefault);
end;

procedure Tfrmmain.imgview321MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer; Layer: TCustomLayer);
var
  np2:tpoint;
  rect1:trect;
  rgb:TColor;
begin
try
  if previewmousedown then begin
    setpreviewselect2;
    exit;
  end;

  np2:=convertabsolutepos(x,y);
  if config.c_pixelcolorview and (imgview321.Bitmap.Empty=false) then begin
    if (np2.X>=0) and (np2.Y>=0) and
      (np2.X<imgview321.Bitmap.Width) and
        (np2.Y<imgview321.Bitmap.Height) then begin
      rgb:=WinColor(imgview321.Bitmap.Pixels[np2.X,np2.Y]);
      Shape1.Brush.Color:=rgb;
      StatusBar1.Panels[5].Text:=
        format('R:%d G:%d B:%d',[(rgb) and $FF,
                                  (rgb shr  8) and $FF,
                                  (rgb shr 16) and $FF]);
    end;
  end;

  if btnselectmode.Checked then begin
    if RBLayerSelect<>nil then begin
      rect1:=MakeRect(RBLayerSelect.Location, rrInside);
      if windows.PtInRect(rect1,np2) then
        setimgview321Cursor(10)
      else
        setimgview321Cursor(crDefault);
    end else
      setimgview321Cursor(crDefault);

    if selectionenabled then begin
      if (np2.X-5 < Xorg) and (Xorg < np2.X+5) and
         (np2.Y-5 < Yorg) and (Yorg < np2.Y+5) then exit;
      Xmov:=np2.X; Ymov:=np2.Y;
      DrawTheRect;
    end;
  end else begin
    if MouseDragging then begin
      imgview321.Scroll(OldMousePos.X - X, OldMousePos.Y - Y);
      OldMousePos := Point(X, Y);
      setpreviewselect;
    end else
      setimgview321Cursor(crDefault);
  end;
except
end;
end;

procedure Tfrmmain.imgview321MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
var
  np2:tpoint;
begin
  if dblclicked then begin
    dblclicked:=false;
    exit;
  end;
  if Button=mbRight then begin
    np2:=mouse.CursorPos;
    TBSubmenuItem7.Popup(np2.X,np2.Y,true);
    exit;
  end;

  previewmousedown:=false;
  if btnselectmode.Checked then begin
    selectionenabled:=false;
  end else begin
    MouseDragging := False;
    setimgview321Cursor(crDefault);
  end;
end;

procedure Tfrmmain.DrawTheRect;
 function NormalizeRect(R: TRect): TRect;
 begin
  with R do
    if Left > Right then
      if Top > Bottom then
        Result := Rect(Right,Bottom,Left,Top)
      else
        Result := Rect(Right,Top,Left,Bottom)
    else
      if Top > Bottom then
        Result := Rect(Left,Bottom,Right,Top)
      else
        Result := Rect(Left,Top,Right,Bottom);
 end;
var
  R:trect;
begin
  R:=rect(xorg,yorg,xmov,ymov);
  R:=normalizerect(R);
  with R do begin
    if left<0 then left:=0;
    if right>ImgView321.bitmap.width then right:=ImgView321.bitmap.width;
    if top<0 then top:=0;
    if bottom>ImgView321.bitmap.height then bottom:=ImgView321.bitmap.height;
  end;
  select(R);
end;

procedure Tfrmmain.Select(R:Trect);
begin
  if RBLayerSelect=nil then
    RBLayerSelect:=TRubberBandLayer.Create(ImgView321.Layers);

  with RBLayerSelect do begin
    Location := FloatRect(-2,-2,-1,-1);
    Handles:=[rhFrame];
    LayerOptions := LOB_VISIBLE or LOB_MOUSE_EVENTS;
    Location := FloatRect(R);
    Scaled := True;
    Visible := True;
    BringToFront;
  end;
  ImgView321.Changed;
end;

procedure Tfrmmain.N6Click(Sender: TObject);
begin
  case listview1.ViewStyle of
    vsIcon:mnu_viewstyle1.Checked:=true;
    vsList:mnu_viewstyle3.Checked:=true;
    vsReport:mnu_viewstyle4.Checked:=true;
  end;
end;

procedure Tfrmmain.N8Click(Sender: TObject);
begin
  case listview1.ViewStyle of
    vsIcon:BrowserListView1.setviewstyle(vsList);
    vsList:BrowserListView1.setviewstyle(vsReport);
    vsReport:BrowserListView1.setviewstyle(vsIcon);
  end;
end;

procedure Tfrmmain.mnuminusClick(Sender: TObject);
var
  NewScale: Single;
begin
  NewScale:=imgview321.Scale-((trunc(imgview321.Scale)+1) / 10);
  if NewScale<0.1 then NewScale:=0.1;
  imgview321.Scale:=NewScale;
  if config.c_keepratio then
    config.ratio:=round(imgview321.Scale*100);
  fitchanged:=true;
  setpreviewselect;
end;

procedure Tfrmmain.mnuplusClick(Sender: TObject);
var
  NewScale: Single;
begin
  NewScale:=imgview321.Scale+((trunc(imgview321.Scale)+1) / 10);
  if NewScale>200 then NewScale:=200;
  imgview321.Scale:=NewScale;
  if config.c_keepratio then
    config.ratio:=round(imgview321.Scale*100);
  fitchanged:=true;
  setpreviewselect;
end;

procedure Tfrmmain.listview1move(idx:integer);
var
  ls:tlistitem;
  flag:boolean;
  pt,pt2:tpoint;
  r:trect;
  c:integer;
  wnd:thandle;
begin
  if idx>listview1.Items.Count-1 then begin
    displaymessage('그림이나 사진이 없습니다.');
    exit;
  end;

  if listview1.Visible=false then begin
    ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
    while ls<>nil do begin
      ls.Selected:=false;
      ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
    end;
    flag:=false;
  end else begin
    c:=listview1.SelCount;
    if c=1 then listview1.Selected.Selected:=false;
    flag:=c>1;
  end;

  BrowserListView1.setdoublebuffered;
  listview1.Items[idx].Selected:=true;
  listview1.Items[idx].MakeVisible(false);

  if flag then begin
    r:=listview1.Items[idx].DisplayRect(drBounds);
    pt:=listview1.ClientToScreen(point(0,0));
    pt.X:=pt.X+r.Left;
    pt.Y:=pt.Y+r.Top;

    windows.GetWindowRect(listview1.Handle,r);
    if windows.PtInRect(r,pt) then begin
      imgmoveblock:=true;
      wnd:=windows.GetFocus;
      GetCursorPos(pt2);
      SetCursorPos(pt.x, pt.y);
      mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
      mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
      SetCursorPos(pt2.x, pt2.y);
      application.ProcessMessages;
      windows.SetFocus(wnd);
      imgmoveblock:=false;
    end;

    if listview1.SelCount<>1 then begin
      ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
      while ls<>nil do begin
        ls.Selected:=false;
        ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
      end;
      BrowserListView1.setdoublebuffered;
      listview1.Items[idx].Selected:=true;
      listview1.Items[idx].MakeVisible(false);
    end;
  end;
  BrowserListView1.updatethumb;
end;

procedure Tfrmmain.mnunextimageClick(Sender: TObject);
var
  i,j:integer;
begin
  if imgmoveblock then exit;
  if programmode=pmnostartview then begin
    for i:=0 to listview1.Items.Count-1 do
      if PThumbImage(listview1.Items[i].Data).imagetype<>itfolder then
        break;
    if listview1.SelCount>0 then
      if listview1.Selected.Index=listview1.Items.Count-1 then begin
        displaymessage('마지막 이미지,사진입니다.');
        exit;
      end else begin
        j:=listview1.Selected.Index+1;
        if j<i then j:=i;
        i:=j;
      end;
    listview1move(i);

  end else begin
    if startviewindex >= startviewlist.Count-1 then
      displaymessage('마지막 이미지,사진입니다.')
    else begin
      inc(startviewindex);
      loadfile(PThumbImage(startviewlist.Items[startviewindex]).name,
        PThumbImage(startviewlist.Items[startviewindex]));
    end;
  end;
end;

procedure Tfrmmain.mnuprevimageClick(Sender: TObject);
var
  i:integer;
  flag:boolean;
begin
  if imgmoveblock then exit;
  if programmode=pmnostartview then begin
    flag:=false;
    for i:=0 to listview1.Items.Count-1 do
      if PThumbImage(listview1.Items[i].Data).imagetype<>itfolder then begin
        flag:=true;
        break;
      end;
    if listview1.SelCount>0 then
      if listview1.Selected.Index<=i then begin
        if flag then displaymessage('처음 이미지,사진입니다.');
        exit;
      end else
        i:=listview1.Selected.Index-1;
    listview1move(i);

  end else begin
    if startviewindex <= 0 then
      displaymessage('처음 이미지,사진입니다.')
    else begin
      dec(startviewindex);
      loadfile(PThumbImage(startviewlist.Items[startviewindex]).name,
        PThumbImage(startviewlist.Items[startviewindex]));
    end;
  end;
end;

procedure Tfrmmain.mnuhomeClick(Sender: TObject);
var
  i,j:integer;
begin
  if imgmoveblock then exit;
  if programmode=pmnostartview then begin
    for i:=0 to listview1.Items.Count-1 do
      if PThumbImage(listview1.Items[i].Data).imagetype<>itfolder then
        break;
    if listview1.SelCount>0 then
      if listview1.Selected.Index<=i then begin
        displaymessage('처음 이미지,사진입니다.');
        exit;
      end;
    listview1move(i);

  end else begin
    if startviewindex <= 0 then
      displaymessage('처음 이미지,사진입니다.')
    else begin
      startviewindex:=0;
      loadfile(PThumbImage(startviewlist.Items[startviewindex]).name,
        PThumbImage(startviewlist.Items[startviewindex]));
    end;
  end;
end;

procedure Tfrmmain.mnuendClick(Sender: TObject);
begin
  if imgmoveblock then exit;
  if programmode=pmnostartview then begin
    if listview1.SelCount>0 then
      if listview1.Selected.Index=listview1.Items.Count-1 then begin
        displaymessage('마지막 이미지,사진입니다.');
        exit;
      end;
    listview1move(listview1.Items.Count-1);

  end else begin
    if startviewindex >= startviewlist.Count-1 then
      displaymessage('마지막 이미지,사진입니다.')
    else begin
      startviewindex:=startviewlist.Count-1;
      loadfile(PThumbImage(startviewlist.Items[startviewindex]).name,
        PThumbImage(startviewlist.Items[startviewindex]));
    end;
  end;
end;

function IsActiveDeskTopOn: Boolean;
var
  h: HWND; 
begin 
  h := FindWindow('Progman', nil); 
  h := FindWindowEx(h, 0, 'SHELLDLL_DefView', nil);
  h := FindWindowEx(h, 0, 'Internet Explorer_Server', nil); 
  Result := h <> 0;
end;

function ChangeWallpaper(aFile: String): Boolean;
const
  CLSID_ActiveDesktop: TGUID = '{75048700-EF1F-11D0-9888-006097DEACF9}'; 
var
  hObj: IUnknown; 
  ADesktop: IActiveDesktop;
  wstr: PWideChar;
begin 
  hObj     := CreateComObject(CLSID_ActiveDesktop);
  ADesktop := hObj as IActiveDesktop; 
  wstr := AllocMem(MAX_PATH); 
  try
    StringToWideChar(aFile, wstr, MAX_PATH);
    ADesktop.SetWallpaper(wstr, 0);
    ADesktop.ApplyChanges(AD_APPLY_ALL or AD_APPLY_FORCE);
  finally
    FreeMem(wstr);
  end;
end;

procedure Tfrmmain.mnuwindowsbackClick(Sender: TObject);
var
  reg: TRegIniFile;
  tfilename:string;
begin
//  tfilename:=GetWindowsDir+'nView 배경화면.bmp';
  tfilename:=GetShellPath(CSIDL_APPDATA)+thisregname;
  sysutils.ForceDirectories(tfilename);
  tfilename:=tfilename+'\nView 배경화면.bmp';

  imgview321.Bitmap.SaveToFile(tfilename);

  reg := TRegIniFile.Create('Control Panel\Desktop');
  try
    with reg do
    begin
      WriteString('', 'Wallpaper', tfilename);
      case (sender as TTBCustomItem).Tag of
        1:begin
         //center
         WriteString('', 'TileWallpaper', '0');
         WriteString('','WallpaperStyle','0');
        end;
        2:begin
         //tile
         WriteString('', 'TileWallpaper', '1');
         WriteString('','WallpaperStyle','0');
        end;
        3:begin
        //resize
         WriteString('', 'TileWallpaper', '0');
         WriteString('','WallpaperStyle','2');
        end;
      end;
    end;
  finally
    reg.Free;
  end;
  SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, nil, SPIF_SENDWININICHANGE);
  if IsActiveDeskTopOn then
     ChangeWallpaper(tfilename);

  MessageDlg('윈도우 배경화면을 변경했습니다.', mtInformation, [mbOk], 0);
end;

procedure Tfrmmain.btnselectmodeClick(Sender: TObject);
begin
  case (sender as TTBCustomItem).Tag of
    1:begin
      btnselectmode.Checked:=true;
    end;
    2:begin
      btnmovemode.Checked:=true;
      if RBLayerSelect<>nil then FreeAndNil(RBLayerSelect);
    end;
  end;
end;

procedure Tfrmmain.mnusaveasClick(Sender: TObject);
var
  SaveDialog:TmySavePictureDialog;
  s,ext:string;
  FBitmap:TFreeWinBitmap;
  NewWidth,NewHeight:integer;
  sfilter:TFreeStretchFilter;
  FreeMemoryIO1:TFreeMemoryIO;
  stream:tmemorystream;
  flag:boolean;
  selectsaveflag:integer;
label reopendialog;
begin
  if currentimage.name='' then exit;
  if (Sender as TTBCustomItem).Tag=1 then begin
    frmresize:=Tfrmresize.Create(self);
    try
      frmresize.SpinEdit1.Value:=imgview321.Bitmap.Width;
      frmresize.SpinEdit2.Value:=imgview321.Bitmap.Height;
      if frmresize.ShowModal<>mrok then exit;
      NewWidth:=frmresize.SpinEdit1.Value;
      NewHeight:=frmresize.SpinEdit2.Value;
      sfilter:=TFreeStretchFilter(frmresize.TypeCombo.ItemIndex);
    finally
      frmresize.Free;
    end;
  end;

reopendialog:
  SaveDialog:=TmySavePictureDialog.Create(self);
  SaveDialog.Filter:=FIU_GetAllFilters2;
  SaveDialog.FilterIndex:=FIU_GetSelectidx(lowercase(ExtractFileExt(currentimage.name)));
  if config.c_uselastdir then
    s:=config.lastdir
  else
    s:=ExtractFilePath(currentimage.name);
  if s[length(s)]<>'\' then s:=s+'\';
  SaveDialog.InitialDir:=s;
  SaveDialog.FileName:=ChangeFileExt(ExtractFileName(currentimage.name),'');
  SaveDialog.ExtraCheckbox.Checked:=config.c_dialogpreview;
  try
    if SaveDialog.Execute=false then exit;
    ext:=FIU_GetSelectExt(SaveDialog.FilterIndex);
    selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(ext),false);
    s:=sysutils.ChangeFileExt(SaveDialog.FileName,ext);
    config.lastdir:=sysutils.ExtractFilePath(s);
  finally
    config.c_dialogpreview:=SaveDialog.ExtraCheckbox.Checked;  
    SaveDialog.Free;
  end;

    if sysutils.FileExists(s) then begin
      if MessageDlg(format('"%s" 파일이 이미 존재합니다.',[ExtractFileName(s)])+#13#10+'덮어 씌우시겠습니까?',
           mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
       goto reopendialog;
    end;
    FBitmap:=TFreeWinBitmap.Create;
    stream:=tmemorystream.Create;
    try
      imgview321.Bitmap.SaveToStream(stream);
      FreeMemoryIO1:=TFreeMemoryIO.Create(stream.Memory,stream.Size);
      try
        if FBitmap.LoadFromMemory(FreeMemoryIO1)=false then begin
          s:=format('%s 파일을 읽을수 없습니다.',[ExtractFileName(currentimage.name)]);
          MessageDlg(s,mtError, [mbOk], 0);
          exit;
        end;
      finally
        FreeMemoryIO1.Free;
      end;

      if (Sender as TTBCustomItem).Tag=1 then
        FBitmap.Rescale(NewWidth,NewHeight,sfilter);

      if comparetext(ExtractFileExt(s),'.gif')=0 then begin
        if FBitmap.IsTransparent then
          FBitmap.SetTransparentBg(nil);
        FBitmap.ConvertTo24Bits;
        FBitmap.ColorQuantize(FIQ_WUQUANT);
      end;

      flag:=FBitmap.Save(s,selectsaveflag);
      if flag=false then begin
        if FBitmap.IsTransparent then
          FBitmap.SetTransparentBg(nil);
        FBitmap.ConvertTo24Bits;
        flag:=FBitmap.Save(s,selectsaveflag);
      end;
      if flag then
        MessageDlg('저장되었습니다.',mtInformation, [mbOk], 0)
      else
        MessageDlg('저장에 실패하였습니다.',mtError, [mbOk], 0);
    finally
      FBitmap.Free;
      stream.Free;
    end;
end;

procedure Tfrmmain.mnuprintClick(Sender: TObject);
var
  frmPrint1:TfrmPrint;

  stream:Tmemorystream;
  FreeMemoryIO1:TFreeMemoryIO;
  bitmap:tbitmap;
  FBitmap: TFreeWinBitmap;
  pdata:PByte;
  SizeInBytes: DWORD;
  flag:boolean;
begin
  flag:=false;
  frmPrint1:=TfrmPrint.Create(self);
  try
    if currentimage.istrans then begin
      FBitmap:=TFreeWinBitmap.Create();
      stream:=Tmemorystream.Create;
      try
        imgview321.Bitmap.SaveToStream(stream);
        FreeMemoryIO1:=TFreeMemoryIO.Create(stream.Memory,stream.Size);
        try
          if FBitmap.LoadFromMemory(FreeMemoryIO1)=false then begin
            MessageDlg(format('%s 파일을 읽을수 없습니다.',[ExtractFileName(currentimage.name)]), mtError, [mbOk], 0);
            exit;
          end;
          if FBitmap.IsTransparent then
            FBitmap.SetTransparentBg(nil);
        finally
          FreeMemoryIO1.Free;
        end;
        FreeMemoryIO1:=TFreeMemoryIO.Create();
        try
          FBitmap.SaveToMemory(FIF_BMP,FreeMemoryIO1);
          FreeMemoryIO1.Acquire(pdata,SizeInBytes);
          stream.Clear;
          stream.Write(pdata^,SizeInBytes);
          stream.Position:=0;
          flag:=true;
          frmPrint1.srcbmp:=tbitmap32.Create;
          frmPrint1.srcbmp.LoadFromStream(stream);
        finally
          FreeMemoryIO1.Free;
        end;
      finally
        Fbitmap.Free;
        stream.Free;
      end;
    end;

    if flag=false then
      frmPrint1.srcbmp:=imgview321.Bitmap;
    frmPrint1.Edit1.Text:=sysutils.ExtractFileName(currentimage.name);
    frmprint1.ShowModal;
  finally
    if flag then frmPrint1.srcbmp.Free;
    frmprint1.Free;    
  end;
end;

procedure Tfrmmain.mnumodechangeClick(Sender: TObject);
begin
  if form1<>nil then begin
    mnufullscreenClick(nil);
    exit;
  end;
  modechange(listview1.Visible);
end;

procedure Tfrmmain.imgview321DblClick(Sender: TObject);
begin
  mnumodechangeClick(nil);
  dblclicked:=true;
end;

procedure Tfrmmain.fittoscreen();
var
  ratio:Single;
  w,h,gap:integer;
begin
  gap:=GetSystemMetrics(SM_CYHSCROLL)+5;
  w:=imgview321.Bitmap.Width;
  h:=imgview321.Bitmap.Height;
  if ((imgview321.Width-gap)>=w) and ((imgview321.Height-gap)>=h) then
    ratio:=1
  else begin
    ratio:=(imgview321.Width-gap) / w;
    if (imgview321.Height-gap) < (ratio*h) then begin
      ratio:=(imgview321.Height-gap) / h;
    end;
  end;
  imgview321.Scale:=ratio;
  fitchanged:=false;
end;

procedure Tfrmmain.mnuratio0Click(Sender: TObject);
var
  S: string;
  I: Integer;
begin
  if (sender as TTBCustomItem).Tag=1 then begin
    fittoscreen();
    config.ratio:=0;
  end else begin
    S := (sender as TTBCustomItem).Caption;
    S := StringReplace(S, '%', '', [rfReplaceAll]);
    S := StringReplace(S, ' ', '', [rfReplaceAll]);
    if S = '' then Exit;
    I := StrToIntDef(S, -1);
    if (I < 1) or (I > 2000) then I:=Round(imgview321.Scale * 100)
    else imgview321.Scale:=I / 100;
    config.ratio:=round(imgview321.Scale*100);
    fitchanged:=true;
  end;
  setpreviewselect;
end;

procedure Tfrmmain.form1Close(Sender: TObject; var Action: TCloseAction);
begin
  imgview321.Parent:=self;
  Action:=caFree;
  form1:=nil;
end;

procedure Tfrmmain.mnufullscreenClick(Sender: TObject);
var
  i:integer;
begin
  if form1<>nil then begin
    form1.Close;
    if listview1.Visible then
      imgview321.Color:=config.c_defaultviewcolor //$00DAD0CD
    else
      imgview321.Color:=config.c_viewcolor;
    imgview321.SetFocus;
  end else begin
    form1:=TForm.Create(self);
    form1.Color:=imgview321.Color;
    form1.BorderStyle:=bsNone;
    form1.FormStyle:=fsStayOnTop;
    imgview321.Parent:=form1;
    form1.OnClose:=form1Close;
    form1.WindowState:=wsMaximized;
    form1.Show;
    imgview321.Color:=config.c_viewcolor;
    imgview321.SetFocus;
  end;
end;

procedure Tfrmmain.applicationOnShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
{
  if windows.GetForegroundWindow<>self.Handle then exit;
  Handled:=true;
  if GetKeyState(VK_CONTROL) < 0 then begin
    case msg.CharCode of
      Ord('S'):mnusaveas.Click;
      else
       Handled:=false;
    end;
  end else if GetKeyState(VK_MENU) < 0 then begin
    case msg.CharCode of
      Ord('S'):N2.Click;
      else
       Handled:=false;
    end;
  end else begin
    case msg.CharCode of
      VK_RETURN:begin
       if imgview321.Focused then begin
         mnumodechangeClick(nil);
       end else
         Handled:=false;
      end;
      VK_F11:mnufullscreenClick(nil);
      VK_ADD:mnuplusClick(nil);
      VK_SUBTRACT:mnuminusClick(nil);
      VK_RIGHT,VK_LEFT,VK_UP,VK_DOWN:
        Handled:=imgview321.Focused;
      else
        Handled:=false;
    end;
  end;     }
end;

procedure Tfrmmain.mnuthumbhighClick(Sender: TObject);
begin
  config.thumbSharpen:=not config.thumbSharpen;
  mnurefreshClick(nil);
end;

procedure Tfrmmain.mnuthumbsize1Click(Sender: TObject);
begin
  config.thumbsize:=strtoint((Sender as tmenuitem).Caption);
  BrowserListView1.Setthumbsize(config.thumbsize);
  mnurefreshClick(nil);
end;

procedure Tfrmmain.mnuvieweffect0Click(Sender: TObject);
begin
  config.vieweffect:=(sender as TTBCustomItem).Tag;
end;

procedure Tfrmmain.mnudeleteClick(Sender: TObject);
function DelDir(dir: string): Boolean;
var
  fos: TSHFileOpStruct;
begin
  ZeroMemory(@fos, SizeOf(fos));
  with fos do
  begin
    wFunc  := FO_DELETE;
    fFlags := FOF_SILENT or FOF_NOCONFIRMATION;
    pFrom  := PChar(dir + #0);
  end;
  Result := (0 = ShFileOperation(fos));
end;
var
  i:integer;
  PThumbImage1:PThumbImage;
  s:string;
  ls:Tlistitem;
  list:tlist;
begin
  if listview1.SelCount=1 then begin
    PThumbImage1:=PThumbImage(listview1.Selected.Data);
    s:=sysutils.ExtractFileName(PThumbImage1.name);
    if s='..' then begin
      MessageDlg('삭제할 수 없습니다.',mtError, [mbOk], 0);
      exit;
    end else
      s:=format('"%s" 삭제 하시겠습니까?',[s]);
  end else
    s:='선택한 항목을 모두 삭제 하시겠습니까?';
  if _messagedlg(self, s, mtConfirmation, mbNo)<>mrYes then
    exit;

  Screen.Cursor:=crHourGlass;
  list:=tlist.Create;
  try
    ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
    while ls<>nil do begin
      PThumbImage1:=PThumbImage(ls.Data);
      list.Add(PThumbImage1);
      ls.Selected:=false;
      ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
    end;

    for i:=list.Count-1 downto 0 do begin
      PThumbImage1:=PThumbImage(list.Items[i]);
      if PThumbImage1.imagetype=itfolder then begin
        s:=sysutils.ExtractFileName(PThumbImage1.name);
        if s='..' then continue;
        DelDir(PThumbImage1.name);
        if DirectoryExists(PThumbImage1.name) then begin
          ShowSystemError(PThumbImage1.name + #13#10 + '삭제에 실패했습니다.');
          exit;
        end else
          BrowserListView1.delete2(PThumbImage1);
      end else begin
        if DeleteFile(PThumbImage1.name)=false then begin
          ShowSystemError(PThumbImage1.name + #13#10 + '삭제에 실패했습니다.');
          exit;
        end else
          BrowserListView1.delete2(PThumbImage1);
      end;
    end;
  finally
    list.Free;
    BrowserListView1.setlistviewcount;
    Screen.Cursor:=crdefault;
  end;

  listview1.Repaint;
  treeview1.RefreshNode(treeview1.Selected,true);
  BrowserListView1.updatethumb;
end;

procedure Tfrmmain.mnurefreshClick(Sender: TObject);
begin
  navigate.navigating:=true;
  parsepath(currentpath);
  navigate.navigating:=false;
end;

procedure Tfrmmain.mnuthumbshowiconClick(Sender: TObject);
begin
  config.thumbshowicon:=not config.thumbshowicon;
  listview1.Invalidate;
end;

procedure Tfrmmain.mnuthumbspace1Click(Sender: TObject);
begin
  config.thumbspace:=strtoint((sender as tmenuitem).Caption);
  BrowserListView1.Setthumbspace(config.thumbspace);
  mnurefreshClick(nil);
end;

procedure Tfrmmain.treeview1Change(Sender: TObject;
  Node: TTreeNode);
var
  s:string;
begin
  if BrowserListView1=nil then exit;
  s:=treeview1.SelectedFolder;
  config.lastpath:=s;
  BrowserListView1.BrowserDirectory(s);
end;

procedure Tfrmmain.listview1DragOver(Sender, Source: TObject; X,Y: Integer; State: controls.TDragState; var Accept: Boolean);
var
  listitem:tlistitem;
  PThumbImage1:PThumbImage;
  dest:string;
  node:ttreenode;
  wnd:thandle;
  r:trect;
  i:integer;
begin
{  with listview1 do begin
   wnd:=ListView_GetHeader(Handle);
   windows.GetWindowRect(wnd,r);
   if (y<(r.Bottom-r.Top)+10) then begin
     SendMessage(Handle,WM_VSCROLL,SB_LINEUP,0);
   end else if (y>ClientHeight-(r.Bottom-r.Top)-10) then begin
     SendMessage(Handle,WM_VSCROLL,SB_LINEDOWN,0);
   end;
  end;
}
  accept:=false;
  if (Source<>ListView1) then exit;
  listitem:=listview1.GetItemAt(x,y);
  if listitem=nil then exit;
  PThumbImage1:=PThumbImage(listitem.Data);
  if (PThumbImage1.imagetype<>itfolder) then
    exit;
  if (ExtractFileName(PThumbImage1.name)='..') then begin
    dest:=findupdir(findupdir(PThumbImage1.name));
  end else begin
    dest:=PThumbImage1.name;
  end;
  accept:=test_movefile(dest);
end;

procedure Tfrmmain.listview1DragDrop(Sender, Source: TObject; X,Y: Integer);
var
  listitem:tlistitem;
  PThumbImage1:PThumbImage;
  dest:string;
  node:ttreenode;
begin
  node:=treeview1.Selected;
  listitem:=listview1.GetItemAt(x,y);
  PThumbImage1:=PThumbImage(listitem.Data);
  if (ExtractFileName(PThumbImage1.name)='..') then begin
    dest:=findupdir(findupdir(PThumbImage1.name));
    if node<>nil then
      node:=treeview1.Selected.Parent;
  end else begin
    dest:=PThumbImage1.name;
  end;
  proc_movefile(dest);
  treeview1.RefreshNode(node,true);
end;

procedure Tfrmmain.treeview1DragOver(Sender, Source: TObject; X,
  Y: Integer; State: controls.TDragState; var Accept: Boolean);
var
  node:ttreenode;
  dest:string;
begin
  with treeview1 do begin
   if (y<10) then begin
     SendMessage(Handle,WM_VSCROLL,SB_LINEUP,0);
     Invalidate;
   end else if (y>(ClientHeight-10)) then begin
     SendMessage(Handle,WM_VSCROLL,SB_LINEDOWN,0);
     Invalidate;
   end;
  end;

  accept:=false;
  if (Source<>ListView1) then exit;
  node:=treeview1.GetNodeAt(x,y);
  if node=nil then exit;
  if (decode_address(currentpath)<>atfolder) then
    exit;
  dest:=GetPAthFromPIDL(TJamShellTreeItem(node.data).AbsolutePIDL);
  if DirectoryExists(dest)=false then exit;
  accept:=test_movefile(dest);
end;

procedure Tfrmmain.treeview1DragDrop(Sender, Source: TObject; X,Y: Integer);
var
  node:ttreenode;
  dest:string;
begin
  node:=treeview1.GetNodeAt(x,y);
  dest:=GetPAthFromPIDL(TJamShellTreeItem(node.data).AbsolutePIDL);
  if sysutils.DirectoryExists(dest)=false then begin
    MessageDlg('이 폴더의 경로를 알 수 없습니다.',mterror, [mbOk], 0);
    exit;
  end;
  proc_movefile(dest);
  treeview1.RefreshNode(node,true);
end;

function Tfrmmain.test_movefile(dest:string):boolean;
var
  s:string;
  PThumbImage1:PThumbImage;
  ls:tlistitem;
begin
  result:=false;
  if dest[length(dest)]<>'\' then dest:=dest+'\';

   ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
   while ls<>nil do begin
      PThumbImage1:=PThumbImage(ls.Data);
      if PThumbImage1.imagetype=itfolder then begin
        s:=sysutils.ExtractFileName(PThumbImage1.name);
        if s='..' then exit;
        if comparetext(PThumbImage1.name,dest+s)=0 then exit;
        s:=PThumbImage1.name;
        if s[length(s)]<>'\' then s:=s+'\';
        if comparetext(dest,s)=0 then exit;
      end else
        break;
     ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
   end;
  result:=true;
end;

procedure Tfrmmain.proc_movefile(dest:string);
function MoveDir(const fromDir, toDir: string): Boolean;
var
  fos: TSHFileOpStruct;
begin
  ZeroMemory(@fos, SizeOf(fos));
  with fos do
  begin
    wFunc  := FO_MOVE;
    fFlags := FOF_FILESONLY;
    pFrom  := PChar(fromDir + #0);
    pTo    := PChar(toDir)
  end;
  Result := (0 = ShFileOperation(fos));
end;
var
  s:string;
  i:integer;
  PThumbImage1:PThumbImage;
  list:tlist;
  ls:tlistitem;
begin
  Screen.Cursor:=crHourGlass;
  list:=tlist.Create;
  try
    ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
    while ls<>nil do begin
      PThumbImage1:=PThumbImage(ls.Data);
      list.Add(PThumbImage1);
      ls.Selected:=false;
      ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
    end;

    if dest[length(dest)]<>'\' then dest:=dest+'\';
    for i:=list.Count-1 downto 0 do begin
      PThumbImage1:=PThumbImage(list.Items[i]);
      if PThumbImage1.imagetype=itfolder then begin
        s:=sysutils.ExtractFileName(PThumbImage1.name);
        if s='..' then continue;
        s:=dest+s;
        if comparetext(PThumbImage1.name,s)=0 then begin
          MessageDlg(s + #13#10 + '같은 폴더입니다.',mterror, [mbOk], 0);
          exit;
        end else if DirectoryExists(s) then begin
          MessageDlg(s + #13#10 + '같은 이름의 폴더가 존재합니다.',mterror, [mbOk], 0);
          exit;
        end;
        MoveDir(PThumbImage1.name,dest);
        if DirectoryExists(PThumbImage1.name) then begin
          ShowSystemError(PThumbImage1.name + #13#10 + '이동에 실패했습니다.');
          exit;
        end else
          BrowserListView1.delete2(PThumbImage1);
      end else begin
        s:=dest+sysutils.ExtractFileName(PThumbImage1.name);
        if sysutils.FileExists(s) then begin
          MessageDlg(s + #13#10 + '같은 이름의 파일이 존재합니다.',mterror, [mbOk], 0);
          exit;
        end;
        if movefile(pchar(PThumbImage1.name),pchar(s))=false then begin
          ShowSystemError(PThumbImage1.name + #13#10 + '이동에 실패했습니다.');
          exit;
        end else
          BrowserListView1.delete2(PThumbImage1);
      end;
    end;
  finally
    list.Free;
    BrowserListView1.setlistviewcount;
    Screen.Cursor:=crdefault;
  end;

  listview1.Repaint;
end;

function Tfrmmain.parsepath(s:string):boolean;
var
  at:taddresstype;
begin
  result:=true;
  at:=decode_address(s);
  case at of
    atfolder:
      treeview1setpath(s);
    atfile:begin
      self.loadfile(s);
    end;
    else
      result:=false;
  end;
end;

procedure Tfrmmain.timerhidemessageTimer(Sender: TObject);
begin
  timerhidemessage.Enabled:=false;
  messagelayer.Visible:=false;
  imgview321.Changed;
end;

procedure Tfrmmain.set_gifposition();
var
  w,h:integer;
begin
  if (panelgif.Visible) and (gifimage<>nil) then begin
    w:=gifimage.Picture.Width;
    h:=gifimage.Picture.Height;
    if w>(imgview321.ClientWidth div 2) then begin
      w:=(imgview321.ClientWidth div 2);
      h:=round(w*gifimage.Picture.Height/gifimage.Picture.Width);
    end;
    if h>(imgview321.ClientHeight div 2) then begin
      h:=(imgview321.ClientHeight div 2);
      w:=round(h*gifimage.Picture.Width/gifimage.Picture.Height);
    end;

    gifimage.Left:=1;
    gifimage.Top:=1;
    gifimage.Width:=w;
    gifimage.Height:=h;

    panelgif.Left:=3;
    panelgif.Top:=imgview321.ClientHeight-gifimage.Height-7;
    panelgif.Width:=gifimage.Width+2;
    panelgif.Height:=gifimage.Height+2;
  end;
end;

procedure Tfrmmain.imgview321Resize(Sender: TObject);
var
  i,w,h,x,y:integer;
begin
  if messagelayer.Visible then begin
    w:=messagelayer.Bitmap.Width;
    h:=messagelayer.Bitmap.Height;
    x:=(imgview321.Width div 2)-(w div 2);
    y:=(imgview321.Height div 2)-(h div 2);
    messagelayer.Location:=FloatRect(x,y,x+w,y+h);
  end;
  if (config.ratio=0) and (fitchanged=false) then
    fittoscreen();
  setpreviewresize;

  set_gifposition();
end;

procedure Tfrmmain.set_config;
begin
  listview1.IconOptions.Arrangement:=TIconArrangement(config.c_thumblistarrange);
  if (listview1.Visible=false) or (form1<>nil) then
    imgview321.Color:=config.c_viewcolor
  else
    imgview321.Color:=config.c_defaultviewcolor;
  if config.c_pixelcolorview=false then begin
    Shape1.Brush.Color:=self.StatusBar1.Color;
    StatusBar1.Panels[5].Text:='';
  end;
  if config.c_showhidden or g_showhidden then begin
    if treeview1<>nil then treeview1.ShowOptions:=treeview1.ShowOptions+[soShowHidden];
  end else begin
    if treeview1<>nil then treeview1.ShowOptions:=treeview1.ShowOptions-[soShowHidden];
  end;
  setpreview;
  if (config.c_cacheenable2=false) and (imgcache<>nil) then
    imgcache.clear;
end;

procedure Tfrmmain.bsSkinSpeedButton4Click(Sender: TObject);
begin
  frmOption:=TfrmOption.Create(self);
  try
    case (sender as TTBCustomItem).Tag of
      0:;
      1:frmOption.PageControl1.ActivePageIndex:=1;
      2:frmOption.PageControl1.ActivePageIndex:=1;
    end;
    if frmOption.ShowModal=mrok then
      set_config;
  finally
    frmOption.Free;
  end;
end;

procedure Tfrmmain.navigateonchange(Sender: TObject);
begin
  btnback.Enabled:=navigate.position>0;
  btnforward.Enabled:=navigate.position<navigate.list.Count-1;
  bsSkinSpeedButton2.Enabled:=true;
end;

procedure Tfrmmain.btnbackClick(Sender: TObject);
begin
  if (Sender as TTBCustomItem).Tag=1 then
    navigate.goback
  else
    navigate.goforward;
  navigate.navigating:=true;
  parsepath(navigate.getcurrentpath.path);
  navigate.navigating:=false;
end;

procedure Tfrmmain.navigateonclick(Sender: TObject);
begin
  navigate.gonavigate((sender as TTBCustomItem).Tag);
  navigate.navigating:=true;
  parsepath(navigate.getcurrentpath.path);
  navigate.navigating:=false;
end;

procedure Tfrmmain.mnunewfolderClick(Sender: TObject);
var
  s,s1,dest:string;
  PThumbImage1:PThumbImage;
  idx:integer;
label reinput1;
begin
  if listview1.Items.Count<1 then exit;
  s:='새 폴더';
reinput1:
  if InputQuery2(self,'새 폴더','폴더 이름을 입력해주세요.',s)=false then
    exit;
  if s='' then exit;
  s1:=deletebadfilenamechar(s);
  if s1<>s then begin
    MessageDlg('사용할 수 없는 문자가 있습니다. ( \ / : * ? " < > | )',mtError, [mbOk], 0);
    goto reinput1;
  end;
  dest:=treeview1.SelectedFolder;
  if dest[length(dest)]<>'\' then dest:=dest+'\';

  if sysutils.DirectoryExists(dest + s) then begin
    MessageDlg('같은 이름의 폴더가 존재합니다.',mterror, [mbOk], 0);
    goto reinput1;
  end else begin
    if CreateDir(dest + s)=false then begin
      ShowSystemError('폴더 생성에 실패했습니다.');
      exit;
    end;
    New(PThumbImage1);
    PThumbImage1.imagetype:=itfolder;
    PThumbImage1.loading:=true;
    PThumbImage1.loaded:=true;    
    PThumbImage1.bitmap:=nil;
    PThumbImage1.name:=dest + s;
    PThumbImage1.desc:='';
    PThumbImage1.time:=DateTimeToFileDate(Now);
    PThumbImage1.size:=0;
    PThumbImage1.smallimgidx:=GetIconIndex(GetAppDirectory,0);

    idx:=BrowserListView1.add(PThumbImage1);
    listview1.Items[idx].Selected:=true;
    listview1.Items[idx].MakeVisible(false);
    listview1.Repaint;

    BrowserListView1.updatethumb;

    treeview1.RefreshNode(treeview1.Selected,true);
  end;
end;

procedure Tfrmmain.pmbrowserlistPopup(Sender: TObject);
var
  i,c,c2:integer;
  PThumbImage1:PThumbImage;
begin
  c:=listview1.SelCount;
  c2:=listview1.Items.Count;
  if c>0 then
    PThumbImage1:=PThumbImage(listview1.Selected.Data);

  mnunewfolder.Enabled:=decode_address(currentpath)=atfolder;

  N37.Enabled:=c=1;
  if N37.Enabled then begin
    if PThumbImage1.imagetype=itfolder then
      N37.Enabled:=listview1.Selected.Caption<>'..';
  end;
  mnudelete.Enabled:=c>0;
  if mnudelete.Enabled then begin
    if PThumbImage1.imagetype=itfolder then
      mnudelete.Enabled:=listview1.Selected.Caption<>'..';
  end;

  n43.Checked:=config.c_enablefilehint;
  n45.Enabled:=c>0;

  mnuthumbhigh.Checked:=config.thumbSharpen;
  mnuthumbshowicon.Checked:=config.thumbshowicon;
  for i:=0 to mnuthumbsize.Count-1 do
    if strtoint(mnuthumbsize.Items[i].Caption)=config.thumbsize then begin
      mnuthumbsize.Items[i].Checked:=true;
      break;
    end;
  for i:=0 to mnuthumbspace.Count-1 do
    if strtoint(mnuthumbspace.Items[i].Caption)=config.thumbspace then begin
      mnuthumbspace.Items[i].Checked:=true;
      break;
    end;

  if listview1.IconOptions.Arrangement=iaTop then n48.Checked:=true
  else n49.Checked:=true;

  case config.thumbeffect of
    0:N46.Checked:=true;
    1:n55.Checked:=true;
    2:n56.Checked:=true;
  end;

  N31.Enabled:=c2>1;
  n51.Enabled:=c2>0;
  n53.Enabled:=c2>0;
  n58.Enabled:=DirectoryExists(treeview1.SelectedFolder);
  N59.Enabled:=c>0;
end;

function EnumWndProc(Wnd: HWND; lParam: Integer): bool; stdcall;
var
  ClassName : array[0..1024] of char;
  dwClass:       DWORD;
begin
  dwClass:=GetClassName(wnd,classname,sizeof(ClassName));
  ClassName[dwClass]:=#0;

  if (StrComp(ClassName,'Auto-Suggest Dropdown')=0)
          then begin
    if IsWindowVisible(wnd) then begin
    HWND(Pointer(lParam)^):=1;
    result:=false
  end;
  end else
    result:=true;
end;

procedure Tfrmmain.applicationOnMessage(var Msg: tagMSG; var Handled: Boolean);
var
  wnd:thandle;
begin
  case Msg.message of
    wm_mousewheel:begin
        wnd:=windows.WindowFromPoint(mouse.CursorPos);
        if GetFocus<>wnd then begin
          windows.SetFocus(wnd);
          sendmessage(wnd, wm_mousewheel, Msg.wParam, Msg.lParam);
          Handled:=true;
        end;
    end;
  end;
end;

procedure Tfrmmain.FormResize(Sender: TObject);
var
  r:trect;
begin
  if treeview1<>nil then
    listview1.Constraints.MaxWidth:=(self.ClientWidth-treeview1.Width)-100;
  r:=TBToolbar2.View.Find(bsSkinButton1).BoundsRect;
  addressbox.Width:=TBToolbar2.ClientWidth-(r.Right-r.Left);
end;

procedure Tfrmmain.N17Click(Sender: TObject);
var
  PThumbImage1:PThumbImage;
  strlist:tstringlist;
  s,s1:string;
  ls:tlistitem;
begin
strlist:=tstringlist.Create;
try
  Screen.Cursor:=crHourGlass;
  try
    ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
    while ls<>nil do begin
       PThumbImage1:=PThumbImage(ls.Data);
       if (PThumbImage1.imagetype=itfile) or (PThumbImage1.imagetype=itbig) then begin
         strlist.Add(PThumbImage1.name);
       end;
      ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
    end;
  finally
    Screen.Cursor:=crdefault;
  end;

  if strlist.Count>1 then
    if MessageDlg(format('%d개의 파일을 여시겠습니까? ',[strlist.Count]), mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
     exit;

  s:=GetAppDirectory2+'nphotoedit.exe';
  if sysutils.FileExists(s)=false then begin
    MessageDlg('편집 프로그램이 없습니다.',mterror, [mbOk], 0);
    exit;
  end;

  if strlist.Count>0 then begin
    s1:=GetAppDirectory+'edits.txt';
    strlist.SaveToFile(s1);
    s:=format('"%s" "%s"',[s,s1]);
    ExecuteFile(s, true);
  end else
    ExecuteFile(s, true);
finally
  strlist.Free;
end;
end;

procedure Tfrmmain.bsSkinSpeedButton1Click(Sender: TObject);
begin
  ShellExecute(0, 'open', 'http://iblogbox.com/nview', nil, nil, SW_SHOW);
end;

procedure Tfrmmain.bsSkinSpeedButton2Click(Sender: TObject);
begin
  if treeview1.Selected.Parent<>nil then
    treeview1.Selected.Parent.Selected:=true;
end;

procedure Tfrmmain.bsSkinButton1Click(Sender: TObject);
var
  s:string;
  i:integer;
begin
  s:=addressbox.Text;
  if sysutils.DirectoryExists(s)=false then begin
    MessageDlg('폴더가 존재하지 않습니다.',mterror, [mbOk], 0);
    exit;
  end;
  if parsepath(s)=false then exit;
  if addressbox.Items.Count>50 then
    addressbox.Items.Delete(addressbox.Items.Count-1);
  for i:=0 to addressbox.Items.Count-1 do
    if comparetext(addressbox.Items.Strings[i],s)=0 then begin
      addressbox.Items.Delete(i);
      break;
    end;
  addressbox.Items.Insert(0,s);
  addressbox.ItemIndex:=0;
end;

function Tfrmmain.get_toolbarpopupPos(toolbar:ttbtoolbar; item:TTBCustomItem): tpoint;
var
  pt:tpoint;
  r,r1,r2:trect;
  wnd:thandle;
  w,h:integer;
begin
  pt:=toolbar.ClientToScreen(point(0,0));
  r:=toolbar.View.Find(item).BoundsRect;
  w:=r.Right-r.Left;
  h:=r.Bottom-r.Top;
  r1.Left:=r.Left+pt.X;
  r1.Right:=r1.Left+w;
  r1.Top:=r.Top+pt.Y;
  r1.Bottom:=r1.Top+h;
  if windows.PtInRect(r1,mouse.CursorPos) then begin
    result.X:=r1.Left;
    result.Y:=r1.Bottom;
  end else begin
    wnd:=windows.WindowFromPoint(mouse.CursorPos);
    windows.GetWindowRect(wnd,r2);
    result.X:=mouse.CursorPos.X-5;
    result.Y:=r2.Bottom;
  end;
end;

 function makecaption(s:widestring):string;
 begin
   if length(s)>50 then begin
     result:=copy(s,1,25)+'...'+copy(s,length(s)-25,25);
   end else
     result:=s;
 end;

procedure Tfrmmain.btnbackPopup(Sender: TTBCustomItem; FromLink: Boolean);
var
  item:TTBCustomItem;
  i:integer;
begin
  btnback.Clear;
  for i:=navigate.position-1 downto 0 do begin
    item:=TTBCustomItem.Create(self);
    item.Caption:=makecaption(Pnavdata(navigate.list.Items[i]).path);
    item.Tag:=i;
    item.OnClick:=navigateonclick;
    btnback.Add(item);
  end;
end;

procedure Tfrmmain.btnforwardPopup(Sender: TTBCustomItem;
  FromLink: Boolean);
var
  item:TTBCustomItem;
  i:integer;
begin
  btnforward.Clear;
  for i:=navigate.position+1 to navigate.list.Count-1 do begin
    item:=TTBCustomItem.Create(self);
    item.Caption:=makecaption(Pnavdata(navigate.list.Items[i]).path);
    item.Tag:=i;
    item.OnClick:=navigateonclick;
    btnforward.Add(item);
  end;
end;

procedure Tfrmmain.N31Click(Sender: TObject);
var
  i,c,start:integer;
  s:string;
begin
  c:=Listview1.Items.Count;
  if c=0 then exit;
  if (Listview1.ViewStyle<>vsicon) and (c>1500) then begin
    if config.getvaluebyinteger('c_alertselectall',0)=0 then begin
      s:='간단히,자세히 보기형식에서 파일리스트가 많은 경우 모두선택이 매우 느릴수 있습니다.';
      s:=s+#13#10+'이런경우 "Home"->"Shift+End" 키를 이용하면 빠르게 모두 선택이 가능합니다.';
      s:=s+#13#10#13#10+'이 메세지를 계속 보시겠습니까?';
      if MessageDlg(s, mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
         config.setvaluebyinteger('c_alertselectall',1);
    end;
  end;
  
  Screen.Cursor:=crHourGlass;
  try
    if Listview1.Items[0].Caption='..' then begin
      Listview1.Items[0].Selected:=false;
      start:=1;
    end else
      start:=0;
    for i := start to Listview1.Items.Count - 1 do
      Listview1.Items[i].Selected := True;
  finally
    Screen.Cursor:=crDefault;
  end;
end;

procedure Tfrmmain.N1Click(Sender: TObject);
begin
  case sortcolumn of
    0:
     if sortreverseorder[sortcolumn]=false then
       mnusorttype.Checked:=true
     else
       N3.Checked:=true;
    2:
     if sortreverseorder[sortcolumn]=false then
       N27.Checked:=true
     else
       N28.Checked:=true;
    3:
     if sortreverseorder[sortcolumn]=false then
       N4.Checked:=true
     else
       N5.Checked:=true;
    4:
     if sortreverseorder[sortcolumn]=false then
       N35.Checked:=true
     else
       N36.Checked:=true;
  end;
end;

procedure Tfrmmain.applicationOnIdle(Sender: TObject; var Done: Boolean);
begin
  StatusBar1.Panels[3].Text:=format('%d %%',[round(ImgView321.Scale*100)]);
  StatusBar1.Panels[6].Text:=format('%d개 선택됨',[listview1.SelCount]);
  vistaaltfixonidle(sender, done);
end;

procedure Tfrmmain.WndProc(var Message: TMessage);
var
  r:trect;
begin
  with Message do
    case Msg of
      wm_timer:begin
        proc_timer(Message);
      end;
    end;
  inherited;
end;

procedure Tfrmmain.TBItem3Click(Sender: TObject);
begin
  if currentimage.name='' then exit;
  clipboard.SetTextBuf(pchar(currentimage.name));
end;

procedure Tfrmmain.TBItem2Click(Sender: TObject);
begin
  imgview321.Bitmap.Rotate90();
  if RBLayerSelect<>nil then FreeAndNil(RBLayerSelect);
  if (config.ratio=0) and (fitchanged=false) then
    fittoscreen();
  if config.c_thumbpreview then
    setpreview;
end;

procedure Tfrmmain.ShowSystemError(msg:string);
var
  s:string;
begin
  s:=SystemErrorMessage;
  if s<>'' then msg:=msg+#13#10#13#10+s;
  MessageDlg(msg, mtError, [mbOk], 0);
end;

procedure Tfrmmain.N37Click(Sender: TObject);
var
  PThumbImage1:PThumbImage;
  s,s1:string;
  x,y:integer;
  r1:trect;
  pt:tpoint;
label reinput1;
label reinput2;
begin
  PThumbImage1:=PThumbImage(listview1.Selected.Data);
  r1:=listview1.Selected.DisplayRect(drBounds);
  pt:=listview1.ClientToScreen(point(0,0));
  x:=r1.Left+pt.X-50;
  y:=r1.Bottom+pt.Y;
  if PThumbImage1.imagetype=itfolder then begin
    s:=listview1.Selected.Caption;
    if s='..' then exit;
reinput1:
    if InputQuery3(self,x,y,'폴더이름 바꾸기','폴더 이름을 입력해주세요.',s)=false then
      exit;
    if s='' then exit;
    s1:=deletebadfilenamechar(s);
    if s1<>s then begin
      MessageDlg('사용할 수 없는 문자가 있습니다. ( \ / : * ? " < > | )',mtError, [mbOk], 0);
      goto reinput1;
    end;
    if comparetext(s,listview1.Selected.Caption)=0 then exit;
    s1:=ExtractFilePath(PThumbImage1.name)+s;
    if sysutils.DirectoryExists(s1) then begin
      MessageDlg('폴더가 존재합니다.',mtError, [mbOk], 0);
      goto reinput1;
    end;
    if windows.MoveFile(pchar(PThumbImage1.name),pchar(s1)) then begin
      PThumbImage1.name:=s1;
      listview1.Repaint;
      treeview1.RefreshNode(treeview1.Selected,true);
    end else
      ShowSystemError('변경할 수 없습니다.');

  end else begin
    s:=ExtractFileName(PThumbImage1.name);
reinput2:
    if InputQuery3(self,x,y,'파일이름 바꾸기','파일 이름을 입력해주세요.',s)=false then
      exit;
    if s='' then exit;
    s1:=deletebadfilenamechar(s);
    if s1<>s then begin
      MessageDlg('사용할 수 없는 문자가 있습니다. ( \ / : * ? " < > | )',mtError, [mbOk], 0);
      goto reinput2;
    end;
    if comparetext(s,ExtractFileName(PThumbImage1.name))=0 then exit;
    s1:=ExtractFilePath(PThumbImage1.name)+s;
    if sysutils.FileExists(s1) then begin
      MessageDlg('파일이 존재합니다.',mtError, [mbOk], 0);
      goto reinput2;
    end;
    if windows.MoveFile(pchar(PThumbImage1.name),pchar(s1)) then begin
      PThumbImage1.name:=s1;
      listview1.Repaint;
      ListView1SelectItem(ListView1, listview1.Selected, true);
    end else
      ShowSystemError('변경할 수 없습니다.');

  end;
end;

procedure Tfrmmain.N38Click(Sender: TObject);
var
  strlist:tstringlist;
  s,s1:string;
begin
 strlist:=tstringlist.Create;
 try
  strlist.Add(currentimage.name);
  if strlist.Count>0 then begin
    s1:=GetAppDirectory+'edits.txt';
    strlist.SaveToFile(s1);
    s:=GetAppDirectory2+'nphotoedit.exe';
    if sysutils.FileExists(s)=false then begin
      MessageDlg('편집 프로그램이 없습니다.',mterror, [mbOk], 0);
      exit;
    end;
    s:=format('"%s" "%s"',[s,s1]);
    ExecuteFile(s, true);
  end;
 finally
   strlist.Free;
 end;
end;

procedure Tfrmmain.TBItem5Click(Sender: TObject);
begin
  frmworkselect:=Tfrmworkselect.Create(self);
  frmworkselect.workmethod:=wmsaveas;
  frmworkselect.ShowModal;
  frmworkselect.Free;
end;

procedure Tfrmmain.TBItem4Click(Sender: TObject);
begin
  frmworkselect:=Tfrmworkselect.Create(self);
  frmworkselect.workmethod:=wmthumb;
  frmworkselect.ShowModal;
  frmworkselect.Free;
end;

Procedure Resample(Src,Dst: TBitmap32; X,Y: Integer; Filter:TStretchFilter);
var
  RectS: TRect;
  RectD: TRect;
  DstClipW,DstClipH:Trect;
  resampler:TCustomResampler;
Begin
  RectS.Top := 0;
  RectS.Left := 0;
  RectS.Right := src.Width;
  RectS.Bottom := src.Height;
  RectD.Top := 0;
  RectD.Left := 0;
  RectD.Right := X;
  RectD.Bottom := Y;

  Dst.Clear(clGray32);
  Dst.Width:=X;
  Dst.Height:=Y;

  case Filter of
    sfNearest:resampler:=TNearestResampler.Create;
    sfDraft:resampler:=TDraftResampler.Create;
    sfLinear:resampler:=TLinearResampler.Create;
  else
    resampler:=TKernelResampler.Create;
    with resampler as TKernelResampler do
      case Filter of
        sfCosine: Kernel := TCosineKernel.Create;
        sfSpline: Kernel := TSplineKernel.Create;
        sfLanczos: Kernel := TLanczosKernel.Create;
        sfMitchell: Kernel := TMitchellKernel.Create;
      end;
  end;
  try
    StretchTransfer(Dst, RectD, RectD, Src, RectS, resampler, dmblend, nil);
  finally
    resampler.Free;
  end;
end;

procedure Tfrmmain.setpreview;
var
  i,w,h,x,y:integer;
  r:trect;
begin
  if imgview321.Bitmap.Empty then exit;
  if preview=nil then
    preview:=TBitmapLayer.Create(imgview321.Layers);

  if imgview321.Bitmap.Width>imgview321.Bitmap.Height then begin
    w:=config.c_thumbpreviewsize;
    previewscale:=w/imgview321.Bitmap.Width;
    h:=round(imgview321.Bitmap.Height*previewscale);
  end else begin
    h:=config.c_thumbpreviewsize;
    previewscale:=h/imgview321.Bitmap.Height;
    w:=round(imgview321.Bitmap.Width*previewscale);
  end;
  if previewscale>1 then begin
    previewscale:=1;  
    w:=imgview321.Bitmap.Width;
    h:=imgview321.Bitmap.Height;
  end;
  Resample(imgview321.Bitmap,preview.Bitmap,w,h,sfNearest);

  r:=rect(0,0,preview.Bitmap.Width,preview.Bitmap.Height);
  for i:=0 to 4 do begin
    with r do
      preview.Bitmap.RaiseRectTS(Left, Top, Right, Bottom, 35 - I * 8);
    InflateRect(R, -1, -1);
  end;

  preview.Bitmap.DrawMode:=dmBlend;
  x:=imgview321.Width-w-10;
  y:=imgview321.Height-h-10;
  preview.Location:=FloatRect(x,y,x+w,y+h);
  preview.Bitmap.MasterAlpha:=config.c_thumbpreviewalpha;

  if previewposition=nil then
    previewposition:=TPositionedLayer.Create(ImgView321.Layers);
  previewposition.Location:=FloatRect(0,0,0,0);
  previewposition.OnPaint:=previewpositionPaint;

  if previewselect=nil then
    previewselect:=TRubberBandLayer.Create(ImgView321.Layers);

  with previewselect do begin
    ChildLayer := previewposition;
    OnResizing:=previewselectResizing;
    Handles:=[rhCenter]; //rhFrame
    LayerOptions := LOB_VISIBLE or LOB_MOUSE_EVENTS or LOB_NO_UPDATE;
    Location := FloatRect(0,0,0,0);
    Visible := True;
    BringToFront;
  end;

  setpreviewselect;
end;

procedure Tfrmmain.previewpositionPaint(Sender: TObject; Buffer: TBitmap32);
var
  r1:TFloatRect;
  r:TRect;
begin
  if Sender is TPositionedLayer then begin
    r1:=(Sender as TPositionedLayer).Location;
    r:=MakeRect(r1);
    if previewselect<>nil then
      previewselect.Location:=r1;

    with Buffer do begin
      Canvas.Brush.Style:=bsClear;
      Canvas.Pen.Color:=config.c_thumbpreviewcolor;
      Canvas.Pen.Width:=2;
      Canvas.Rectangle(r);
    end;
    Buffer.Changed;
  end;
end;

procedure Tfrmmain.setpreviewselect;
var
  pt:tpoint;
  r1,r2:TFloatRect;
  x,y,w,h:single;
  minsize:integer;
begin
try
  if (preview=nil) then exit;
  r1:=previewposition.Location;
  r2:=preview.Location;

  pt:=imgview321.ControlToBitmap(point(0,0));
  x:=pt.X;
  if x<0 then x:=0;
  x:=previewscale*x;
  y:=pt.Y;
  if y<0 then y:=0;
  y:=previewscale*y;

  pt:=imgview321.ControlToBitmap(point(imgview321.Width,imgview321.Height));
  w:=previewscale*pt.X;
  h:=previewscale*pt.Y;
  if (w<=0) or (h<=0) then exit;

  r1.Left:=r2.Left+x;
  r1.Top:=r2.Top+y;
  r1.Right:=r2.Left+w;
  r1.Bottom:=r2.Top+h;
  w:=r1.Right-r1.Left;
  h:=r1.Bottom-r1.Top;

  minsize:=20;
  if (w>h) and (w<minsize) then begin
    r1.Right:=r1.Left+minsize;
    if r1.Right>r2.Right then begin
      r1.Right:=r2.Right;
      r1.Left:=r1.Right-minsize;
    end;
    h:=(h*minsize)/w;
    r1.Bottom:=r1.Top+h;
    if r1.Bottom>r2.Bottom then begin
      r1.Bottom:=r2.Bottom;
      r1.Top:=r1.Bottom-h;
    end;
  end else if (h<minsize) then begin
    r1.Bottom:=r1.Top+minsize;
    if r1.Bottom>r2.Bottom then begin
      r1.Bottom:=r2.Bottom;
      r1.Top:=r1.Bottom-minsize;
    end;
    w:=(w*minsize)/h;
    r1.Right:=r1.Left+w;
    if r1.Right>r2.Right then begin
      r1.Right:=r2.Right;
      r1.Left:=r1.Right-w;
    end;
  end;

  if r1.Right>r2.Right then r1.Right:=r2.Right;
  if r1.Bottom>r2.Bottom then r1.Bottom:=r2.Bottom;

  previewposition.Location:=r1;

  if (config.c_thumbpreview=false) then begin
    freeandnil(previewselect);
    freeandnil(previewposition);
    freeandnil(preview);
    exit;
  end;
  if (abs(r1.Left-r2.Left)<2) and (abs(r1.Right-r2.Right)<2) and
    (abs(r1.Top-r2.Top)<2) and (abs(r1.Bottom-r2.Bottom)<2) then begin
    previewposition.Visible:=false;
    preview.Visible:=false;
  end else begin
    previewposition.Visible:=true;
    preview.Visible:=true;
  end;
except
end;
end;

procedure Tfrmmain.setpreviewselect2;
var
  r1,r2:TFloatRect;
  x,y:integer;
begin
  if (preview=nil) then exit;

  r1:=previewposition.Location;
  r2:=preview.Location;

  x:=round(((r1.Left-r2.Left)+((r1.Right-r1.Left)/2))/previewscale);
  y:=round(((r1.Top-r2.Top)+((r1.Bottom-r1.Top)/2))/previewscale);
  imgview321.ScrollToCenter(x,y);
end;

procedure Tfrmmain.setpreviewresize;
var
  w,h,x,y:integer;
  r1:TFloatRect;
begin
  if (preview=nil) then exit;

  r1:=preview.Location;
  w:=round(r1.Right-r1.Left);
  x:=imgview321.Width-w-10;
  h:=round(r1.Bottom-r1.Top);
  y:=imgview321.Height-h-10;
  preview.Location:=FloatRect(x,y,x+w,y+h);
  
  setpreviewselect;
end;

procedure Tfrmmain.previewselectResizing(Sender: TObject;
  const OldLocation: TFloatRect; var NewLocation: TFloatRect;
  DragState: TDragState; Shift: TShiftState);
var
  r1,r2:TFloatRect;
  w,h:single;
begin
  r1:=NewLocation;
  r2:=preview.Location;

  w:=r1.Right-r1.Left;
  h:=r1.Bottom-r1.Top;
  if r1.Left<r2.Left then begin
    r1.Left:=r2.Left;
    r1.Right:=r1.Left+w;
  end;
  if r1.Right>r2.Right then begin
    r1.Right:=r2.Right;
    r1.Left:=r1.Right-w;
  end;
  if r1.Top<r2.Top then begin
    r1.Top:=r2.Top;
    r1.Bottom:=r1.Top+h;
  end;
  if r1.Bottom>r2.Bottom then begin
    r1.Bottom:=r2.Bottom;
    r1.Top:=r1.Bottom-h;
  end;
  NewLocation:=r1;
end;

procedure Tfrmmain.N26Click(Sender: TObject);
begin
  config.c_thumbpreview:=not config.c_thumbpreview;
  setpreview;
end;

procedure Tfrmmain.N40Click(Sender: TObject);
begin
  case (sender as TTBCustomItem).Tag of
    0: imgview321.Bitmap.FlipVert();
    1: imgview321.Bitmap.FlipHorz();
    2: imgview321.Bitmap.Rotate90();
    3: imgview321.Bitmap.Rotate180();
    4: imgview321.Bitmap.Rotate270();
    else
      exit;
  end;
  if RBLayerSelect<>nil then FreeAndNil(RBLayerSelect);
  if (config.ratio=0) and (fitchanged=false) then
    fittoscreen();
  if config.c_thumbpreview then
    setpreview;
end;

procedure Tfrmmain.displaymessage(s:string);
var
  r:trect;
  i,w,h,x,y:integer;
  bmp:tbitmap;
begin
  bmp:=tbitmap.Create;
  bmp.Width:=1;
  bmp.Height:=1;
  bmp.Canvas.Font.Name:='굴림';
  bmp.Canvas.Font.Size:=11;
  bmp.Canvas.Font.Color:=clblack;

  w:=bmp.Canvas.TextWidth(s)+50;
  h:=bmp.Canvas.TextHeight('gh')*2;
  bmp.Width:=w;
  bmp.Height:=h;

  r:=rect(0,0,w,h);
  bmp.Canvas.Brush.Color:=clwhite;
  bmp.Canvas.FillRect(r);
  DrawText(bmp.Canvas.Handle, PChar(s), Length(s), r, DT_CENTER or DT_VCENTER or DT_SINGLELINE);

  messagelayer.Bitmap.Assign(bmp);
  r:=rect(0,0,w,h);
  for i:=0 to 4 do begin
    with r do
      messagelayer.Bitmap.RaiseRectTS(Left, Top, Right, Bottom, 35 - I * 8);
    InflateRect(R, -1, -1);
  end;
  bmp.Free;

  messagelayer.Bitmap.DrawMode:=dmBlend;
  x:=(imgview321.Width div 2)-(w div 2);
  y:=(imgview321.Height div 2)-(h div 2);
  messagelayer.Location:=FloatRect(x,y,x+w,y+h);
  messagelayer.Bitmap.MasterAlpha:=170;
  messagelayer.Visible:=true;

  timerhidemessage.Enabled:=false;
  timerhidemessage.Enabled:=true;
end;

procedure Tfrmmain.TBItem6Click(Sender: TObject);
begin
  frmabout:=Tfrmabout.Create(self);
  try
    frmabout.Caption:=self.Caption;
    frmabout.ShowModal;
  finally
    frmabout.Free;
  end;
end;

procedure Tfrmmain.N42Click(Sender: TObject);
begin
  frmrename:=Tfrmrename.Create(self);
  frmrename.Edit3.Text:=treeview1.SelectedFolder;
  frmrename.ShowModal;
  if frmrename.renameok then
    mnurefreshClick(nil);
  frmrename.Free;
end;

procedure Tfrmmain.N43Click(Sender: TObject);
begin
  config.c_enablefilehint:=not config.c_enablefilehint;
end;

procedure Tfrmmain.addressboxKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  addressbox.Tag:=0;
  if key=13 then begin
    bsSkinButton1Click(nil);
    addressbox.DroppedDown:=false;
    key:=0;
  end;
end;

procedure Tfrmmain.addressboxClick(Sender: TObject);
begin
  if addressbox.Tag=1 then begin
    if addressbox.ItemIndex>=0 then
      addressbox.Text:=addressbox.Items[addressbox.ItemIndex];
    bsSkinButton1Click(nil);
  end;
  addressbox.Tag:=0;
end;

procedure Tfrmmain.addressboxDropDown(Sender: TObject);
begin
  addressbox.Tag:=1;
end;

procedure Tfrmmain.HookWndProc(var Message: TMessage);
begin
  with Message do begin
    case Msg of
     EM_SETSEL:begin
       if (Fkillfocus=false) and (GetFocus<>TAccessComboBox(addressbox).EditHandle) then exit;
       if WParam=LParam then begin
         WParam:=10000;
         LParam:=10000;
       end else if (WParam=0) then begin
         LParam:=length(addressbox.Text);
       end;
       Fkillfocus:=false;
     end;
     WM_KILLFOCUS:begin
       Fkillfocus:=true;
     end;
    end;
    Result := CallWindowProc(OldWndProc, TAccessComboBox(addressbox).EditHandle,
       Msg, wParam, lParam);
  end;
end;

procedure Tfrmmain.TBItem7Click(Sender: TObject);
begin
  if MessageDlg('모두 삭제 하시겠습니까?',
       mtConfirmation, [mbYes, mbNo], 0) = mrNo then
    exit;
  addressbox.Items.Clear;
  addressbox.Text:=currentpath;
end;

procedure Tfrmmain.TBSubmenuItem5Popup(Sender: TTBCustomItem;
  FromLink: Boolean);
begin
  TBItem1.Enabled:=currentimage.name<>'';
  TBItem11.Enabled:=listview1.SelCount>0;
end;

procedure Tfrmmain.OneInstance1InstanceStarted(Sender: TObject; params: TStringList);
begin
  if params.Count>0 then
    startviewcheck(params.Strings[0],false);
end;

procedure CopyFilesToClipboard(FileList: string);
var
  DropFiles: PDropFiles;
  hGlobal: THandle;
  iLen: Integer;
begin
  iLen := Length(FileList) + 2;
  FileList := FileList + #0#0;
  hGlobal := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,
    SizeOf(TDropFiles) + iLen);
  if (hGlobal = 0) then raise Exception.Create('Could not allocate memory.');
  begin
    DropFiles := GlobalLock(hGlobal);
    DropFiles^.pFiles := SizeOf(TDropFiles);
    Move(FileList[1], (PChar(DropFiles) + SizeOf(TDropFiles))^, iLen);
    GlobalUnlock(hGlobal);
    Clipboard.SetAsHandle(CF_HDROP, hGlobal);
  end;
end;

procedure Tfrmmain.N44Click(Sender: TObject);
begin
  if currentimage.name='' then exit;
  Screen.Cursor:=crHourGlass;
  try
    CopyFilesToClipboard(currentimage.name);
  finally
    Screen.Cursor:=crdefault;
  end;
end;

procedure Tfrmmain.N45Click(Sender: TObject);
var
  s:string;
  PThumbImage1:PThumbImage;
  ls:tlistitem;
begin
 Screen.Cursor:=crHourGlass;
 try
   ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
   while ls<>nil do begin
     PThumbImage1:=PThumbImage(ls.Data);
     if PThumbImage1.imagetype=itfolder then begin
       if s<>'' then s:=s+#0;
       s:=s+PThumbImage1.name;
     end else begin
       if s<>'' then s:=s+#0;
       s:=s+PThumbImage1.name;
     end;
     ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
   end;
   CopyFilesToClipboard(s);
 finally
   Screen.Cursor:=crdefault;
 end;
end;

procedure Tfrmmain.TBSubmenuItem1Popup(Sender: TTBCustomItem;
  FromLink: Boolean);
var
  i,v:integer;
  s:string;
begin
  if config.ratio=0 then
    mnuratio0.Checked:=true
  else begin
    for i:=0 to TBSubmenuItem1.Count-1 do begin
      if TBSubmenuItem1.Items[i].Checked then
        TBSubmenuItem1.Items[i].Checked:=false;
      s:=TBSubmenuItem1.Items[i].Caption;
      s:=StringReplace(s, '%', '', [rfReplaceAll]);
      s:=StringReplace(s, ' ', '', [rfReplaceAll]);
      v:=StrToIntDef(s, -1);
      if config.ratio=v then begin
        TBSubmenuItem1.Items[i].Checked:=true;
        break;
      end;
    end;
  end;
end;

procedure Tfrmmain.browsertimerTimer(Sender: TObject);
begin
  browsertimer.Enabled:=false;
  if sysutils.DirectoryExists(browserpath)=false then
    browserpath:='c:\';
  treeview1setpath(browserpath);
end;

procedure Tfrmmain.N48Click(Sender: TObject);
begin
  listview1.IconOptions.Arrangement:=TIconArrangement((Sender as tmenuitem).Tag);
  config.c_thumblistarrange:=(Sender as tmenuitem).Tag;
end;

procedure Tfrmmain.listview1OnEditing(Sender: TObject; Item: TListItem;var AllowEdit: Boolean);
begin
  AllowEdit:=false;
  if config.c_enablerenameclick then
    N37Click(nil);
end;

procedure Tfrmmain.TBItem8Click(Sender: TObject);
var
  s:string;
begin
  s:=GetAppDirectory2+'nphotoedit.exe';
  if sysutils.FileExists(s)=false then begin
    MessageDlg('편집 프로그램이 없습니다.',mterror, [mbOk], 0);
    exit;
  end;
  ExecuteFile(s, true);
end;

procedure Tfrmmain.Button1Click(Sender: TObject);
var
  FBitmap:TFreeWinBitmap;
  fif:FREE_IMAGE_FORMAT;
  mbitmap:TFreeMultiBitmap;
  i,j,t:integer;
begin
  exit;

  FBitmap:=TFreeWinBitmap.Create;
  mbitmap:=TFreeMultiBitmap.Create(true);
  mbitmap.Open('test.gif',true,false);

  FBitmap.Load('Autumn Leaves.jpg');
  FBitmap.ColorQuantize(FIQ_WUQUANT);
//  FBitmap.ConvertTo16Bits555;
//  Fbitmap.ConvertToStandartType(false);
  mbitmap.AppendPage(FBitmap);
  FBitmap.Load('Desert Landscape.jpg');
  FBitmap.ColorQuantize(FIQ_WUQUANT);
//  FBitmap.ConvertTo16Bits555;
//  Fbitmap.ConvertToStandartType(false);
  mbitmap.AppendPage(FBitmap);
{
  FBitmap.Load('D:\windows\깃털.bmp');
  mbitmap.AppendPage(FBitmap);
  FBitmap.Load('D:\windows\낚시.bmp');
  mbitmap.AppendPage(FBitmap);
}
  mbitmap.Close(GIF_DEFAULT);
  mbitmap.Free;
  FBitmap.Free;
end;

procedure Tfrmmain.TBItem9Click(Sender: TObject);
var
  s:string;
  data:Pfavoritedata;
begin
  if programmode=pmstartview then begin
    if startviewlist.Count>0 then
      s:=ExtractFilePath(PThumbImage(startviewlist.Items[0]).name);
  end else begin
    if treeview1<>nil then
      s:=treeview1.SelectedFolder;
  end;
  if (length(s)>0) and (s[length(s)]='\') then delete(s,length(s),1);
  frmfavadd:=Tfrmfavadd.Create(self);
  try
    frmfavadd.Caption:='즐겨찾기 추가';
    frmfavadd.Edit1.Text:=sysutils.ExtractFileName(s);
    frmfavadd.Edit2.Text:=s;
    if frmfavadd.ShowModal=mrok then begin
      new(data);
      data.title:=frmfavadd.Edit1.Text;
      data.path:=frmfavadd.Edit2.Text;
      favorite.list.Add(data);
      favorite.save;
    end;
  finally
    frmfavadd.Free;
  end;
end;

procedure Tfrmmain.TBSubmenuItem6Popup(Sender: TTBCustomItem; FromLink: Boolean);
var
  i:integer;
  data:Pfavoritedata;
  item:TTBItem;
  s:string;
begin
  for i:=TBSubmenuItem6.Count-1 downto 3 do
    TBSubmenuItem6.Items[i].Free;
  for i:=0 to favorite.list.Count-1 do begin
    data:=Pfavoritedata(favorite.list.Items[i]);
    item:=TTBItem.Create(self);
    item.Caption:=cutstring(data.title,60);
    item.OnClick:=favoriteOnClick;
    item.Tag:=i;
    item.ImageIndex:=12;
    TBSubmenuItem6.Add(item);
  end;
  if programmode=pmstartview then begin
    if startviewlist.Count>0 then
      s:=ExtractFilePath(PThumbImage(startviewlist.Items[0]).name);
  end else begin
    if treeview1<>nil then
      s:=treeview1.SelectedFolder;
  end;
  TBItem9.Enabled:=s<>'';
end;

procedure Tfrmmain.favoriteOnClick(Sender: TObject);
var
  s:String;
begin
  if (listview1.Visible=false) then
    modechange(false);
  s:=Pfavoritedata(favorite.list.Items[(sender as TTBItem).Tag]).path;
  treeview1setpath(s);
end;

procedure Tfrmmain.TBItem10Click(Sender: TObject);
begin
  frmfav:=Tfrmfav.Create(self);
  try
    frmfav.ShowModal;
  finally
    frmfav.Free;
  end;
end;

procedure Tfrmmain.proc_find();
var
  flag:boolean;
  idx:integer;
begin
 Screen.Cursor:=crHourGlass;
 try
  if findindex=-1 then
    Deselectall();

  flag:=false;
  idx:=BrowserListView1.find(findindex,findword);
  if idx>=0 then begin
    flag:=true;
    findindex:=idx;
    listview1.Items[idx].Selected:=true;
    listview1.Items[idx].Focused:=true;
    listview1.Items[idx].MakeVisible(false);
    BrowserListView1.updatethumb;
  end;
 finally
   Screen.Cursor:=crdefault;
 end;

  if flag=false then begin
    if findindex<0 then
      MessageDlg('찾는 단어를 포함한 파일이 없습니다.',mtinformation, [mbOk], 0)
    else
      MessageDlg('끝까지 찾았습니다.',mtinformation, [mbOk], 0);
    findindex:=-1;
  end;
end;

procedure Tfrmmain.N51Click(Sender: TObject);
var
  s:string;
begin
  s:=config.c_lastfindword;
  if MyInputBox(self,'찾을단어','찾을 단어를 입력해 주세요.',false,s)=false then
    exit;
  findword:=trim(s);
  config.c_lastfindword:=findword;
  if findword='' then exit;
  findindex:=-1;
  proc_find();
end;

procedure Tfrmmain.N53Click(Sender: TObject);
begin
  if findword='' then N51Click(nil)
  else proc_find();
end;

procedure Tfrmmain.load_gifaniimage(filename:string);
var
  stream:Tmemorystream;
begin
  if gifimage=nil then begin
    gifimage:=timage.Create(self);
    gifimage.Stretch:=true;
    gifimage.Cursor:=crHandPoint;
    gifimage.ShowHint:=true;
    gifimage.Hint:='GIF 애니메이션 세부 이미지 보기';
    gifimage.OnClick:=gifimageOnClick;
  end;
  gifimage.Parent:=panelgif;
  if gif=nil then
    gif:=Tgifimage.Create;
  gif.LoadFromFile(filename);
  gifimage.Picture.Assign(gif);

  panelgif.Visible:=true;
  set_gifposition();
end;

procedure Tfrmmain.gifimageOnClick(Sender: TObject);
begin
  frmgif:=Tfrmgif.Create(self);
  try
    frmgif.gif:=gif;
    frmgif.ShowModal;
  finally
    frmgif.Free;
  end;
end;

procedure Tfrmmain.TBItem12Click(Sender: TObject);
begin
  ShellExecute(0, 'open', 'http://boom4u.net/lyrics', nil, nil, SW_SHOW);
end;

procedure Tfrmmain.N55Click(Sender: TObject);
begin
  config.thumbeffect:=(Sender as tmenuitem).Tag;
  mnurefreshClick(nil);
end;

procedure Tfrmmain.TBItem15Click(Sender: TObject);
begin
  frmratio:=Tfrmratio.Create(self);
  try
    frmratio.spinedit1.Value:=config.userratio;
    if frmratio.ShowModal=mrok then begin
      config.userratio:=frmratio.spinedit1.Value;
      config.ratio:=frmratio.spinedit1.Value;
      imgview321.Scale:=config.ratio / 100;
      fitchanged:=true;
    end;
  finally
    frmratio.Free;
  end;
end;

procedure Tfrmmain.TBItem16Click(Sender: TObject);
var
  s:string;
begin
  s:=format('캐쉬 총크기: %s, 캐쉬 갯수: %d',[ConvertSize(imgcache.gettotsize), imgcache.list.Count]);
  if config.c_cacheenable2 then
    s:=s+#13#10+'(현재 캐쉬 사용함으로 설정 되어있습니다.)'
  else
    s:=s+#13#10+'(현재 캐쉬 사용안함으로 설정 되어있습니다.)';
  s:=s+#13#10#13#10+'캐쉬된 내용을 모두 비우시겠습니까?';

  if MessageDlg(s, mtConfirmation, [mbYes, mbNo], 0)=mrYes then
    imgcache.clear;
end;

procedure Tfrmmain.proc_timer(Message:TMessage);
begin
{  case Message.WParam of
    1:begin
      KillTimer(handle, 1);
    end;
  end;}
end;

procedure Tfrmmain.TBSubmenuItem7Popup(Sender: TTBCustomItem;
  FromLink: Boolean);
var
  i:integer;
begin
  mnufullscreen.Checked:=form1<>nil;
  N26.Checked:=config.c_thumbpreview;

  mnusaveas.Enabled:=currentimage.name<>'';
  n2.Enabled:=currentimage.name<>'';
  mnucopyclipboard.Enabled:=currentimage.name<>'';
  N33.Enabled:=currentimage.name<>'';
  mnuprint.Enabled:=currentimage.name<>'';
  n38.Enabled:=currentimage.name<>'';
  TBItem18.Enabled:=currentimage.name<>'';
  n39.Enabled:=currentimage.name<>'';
  n10.Enabled:=currentimage.name<>'';
  mnuvieweffect.Enabled:=not(listview1.Visible and (form1=nil));
  n44.Enabled:=currentimage.name<>'';

  for i:=0 to mnuvieweffect.Count-1 do
    if mnuvieweffect.Items[i].Tag=config.vieweffect then begin
      mnuvieweffect.Items[i].Checked:=true;
      break;
    end;
end;

procedure Tfrmmain.Deselectall();
var
  ls:tlistitem;
  pt,pt2:tpoint;
  r:trect;
  c:integer;
  wnd:thandle;
begin
  if listview1.Visible=false then begin
    ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
    while ls<>nil do begin
      ls.Selected:=false;
      ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
    end;
    exit;
  end;

  c:=listview1.SelCount;
  if c=0 then exit;
  if c=1 then
    listview1.Selected.Selected:=false
  else begin
    ls:=listview1.TopItem;
    if ls=nil then
      ls:=listview1.GetNearestItem(point(0,0),sdAll);
    if ls<>nil then begin
      r:=ls.DisplayRect(drBounds);
      pt:=listview1.ClientToScreen(point(0,0));
      pt.X:=pt.X+r.Left;
      pt.Y:=pt.Y+r.Top;

      windows.GetWindowRect(listview1.Handle,r);
      if windows.PtInRect(r,pt) then begin
        imgmoveblock:=true;
        wnd:=windows.GetFocus;
        GetCursorPos(pt2);
        SetCursorPos(pt.x, pt.y);
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        SetCursorPos(pt2.x, pt2.y);
        application.ProcessMessages;
        windows.SetFocus(wnd);
        imgmoveblock:=false;
      end;
    end;

    if listview1.SelCount<>1 then begin
      ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
      while ls<>nil do begin
        ls.Selected:=false;
        ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
      end;
    end else
      listview1.Selected.Selected:=false
  end;
end;

procedure Tfrmmain.TBToolbar1ShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  case msg.CharCode of
    VK_PRIOR,VK_NEXT,vk_return,vk_home,vk_end:
      Handled:=not imgview321.Focused;
    ord('C'):begin
      if GetKeyState(VK_CONTROL) < 0 then
        Handled:=not imgview321.Focused;
    end;
  end;
end;

procedure Tfrmmain.PanelWndProc(var Message: TMessage);
begin
  with Message do
    case Msg of
      WM_ERASEBKGND:begin
        Message.Result:=1;
        exit;
      end;
    end;
  FpanelWndProc(Message);
end;

procedure Tfrmmain.N58Click(Sender: TObject);
begin
  ShellExecute(0, 'open', pchar(treeview1.SelectedFolder), nil, nil, SW_SHOW);
end;

procedure Tfrmmain.mnucopyclipboardClick(Sender: TObject);
var
  tempsrcrect,tempdstrect:TRect;
  bitmap:Tbitmap32;
begin
  if currentimage.name='' then exit;
  if RBLayerSelect<>nil then begin
    bitmap:=Tbitmap32.Create;
    try
      tempsrcRect:=MakeRect(RBLayerSelect.Location, rrInside);
      with tempdstRect do begin
         Left := 0;
         Top := 0;
         Right := tempsrcRect.Right - tempsrcRect.Left;
         Bottom := tempsrcRect.Bottom - tempsrcRect.Top;
         bitmap.SetSize(Right, Bottom);
      end;
      bitmap.Draw(tempdstRect, tempsrcRect, imgview321.Bitmap.Canvas.Handle);
      CopyBitmap32ToClipboard(bitmap);
    finally
      bitmap.Free;
    end;
  end else
    CopyBitmap32ToClipboard(imgview321.Bitmap);
//  MessageDlg('클립보드에 복사되었습니다.',mtInformation, [mbOk], 0);
end;

procedure Tfrmmain.N57Click(Sender: TObject);
type
  T_proc_imageshack_upload = procedure (strlist:tstringlist); stdcall;
var
  DllHandle:thandle;
  proc_imageshack_upload:T_proc_imageshack_upload;
  strlist:tstringlist;
  ls:tlistitem;
  PThumbImage1:PThumbImage;
begin
strlist:=tstringlist.Create;
try
  Screen.Cursor:=crHourGlass;
  try
    ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
    while ls<>nil do begin
       PThumbImage1:=PThumbImage(ls.Data);
       if (PThumbImage1.imagetype=itfile) or (PThumbImage1.imagetype=itbig) then begin
         strlist.Add(PThumbImage1.name);
       end;
      ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
    end;
  finally
    Screen.Cursor:=crdefault;
  end;
{
  if strlist.Count=0 then begin
    MessageDlg('선택한 파일이 없습니다.',mterror, [mbOk], 0);
    exit;
  end;
}
  DllHandle:=LoadLibrary(PChar(GetAppDirectory2+'libupload.dll'));
  if DllHandle>0 then begin
    try
      proc_imageshack_upload:=GetProcAddress(DllHandle, 'proc_imageshack_upload');
      if assigned(proc_imageshack_upload) then begin
{        if strlist.Count>0 then
          if MessageDlg(format('%d개의 파일을 무료이미지 업로드 하시겠습니까? ',[strlist.Count]),
             mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
           exit;}
        proc_imageshack_upload(strlist);
      end else
        MessageDlg('오류입니다.',mterror, [mbOk], 0);
    finally
      freelibrary(DllHandle);
    end;
  end else
    MessageDlg('필요한 라이브러리를 읽을 수 없습니다. 프로그램 재설치가 필요할 수 있습니다.',mterror, [mbOk], 0);
finally
  strlist.Free;
end;
end;

procedure Tfrmmain.TBItem18Click(Sender: TObject);
type
  T_proc_imageshack_upload = procedure (strlist:tstringlist); stdcall;
var
  DllHandle:thandle;
  proc_imageshack_upload:T_proc_imageshack_upload;
  strlist:tstringlist;
begin
strlist:=tstringlist.Create;
try
  strlist.Add(currentimage.name);

  DllHandle:=LoadLibrary(PChar(GetAppDirectory2+'libupload.dll'));
  if DllHandle>0 then begin
    try
      proc_imageshack_upload:=GetProcAddress(DllHandle, 'proc_imageshack_upload');
      if assigned(proc_imageshack_upload) then begin
        proc_imageshack_upload(strlist);
      end else
        MessageDlg('오류입니다.',mterror, [mbOk], 0);
    finally
      freelibrary(DllHandle);
    end;
  end else
    MessageDlg('필요한 라이브러리를 읽을 수 없습니다. 프로그램 재설치가 필요할 수 있습니다.',mterror, [mbOk], 0);
finally
  strlist.Free;
end;
end;

procedure Tfrmmain.checkfolder(path:string);
var
  FHandle:thandle;
  fd:WIN32_FIND_DATA;
  s,s1:string;
  i:integer;
begin
  if (config.c_showhidden=false) and (g_showhidden=false) then begin
    s:=path;
    if (length(s)>0) and (s[length(s)]<>'\') then s:=s+'\';
    for i:=length(s) downto 1 do begin
      if s[i]<>'\' then continue;
      s1:=copy(s,1,i-1);
      FHandle:= Windows.FindFirstFile(PChar(s1), FD);
      if FHandle <> INVALID_HANDLE_VALUE then begin
        if (fd.dwFileAttributes and FILE_ATTRIBUTE_HIDDEN)>0 then begin
          g_showhidden:=true;
          if treeview1<>nil then treeview1.ShowOptions:=treeview1.ShowOptions+[soShowHidden];
          break;
        end;
      end;
      Windows.FindClose(FHandle);
    end;
  end;
end;

procedure Tfrmmain.loadingtimerTimer(Sender: TObject);
begin
  Screen.Cursor:=crHourGlass;
  if gettickcount-loadingtime>2500 then begin
    loadingtime:=gettickcount;
    displaymessage('파일리스트를 가져오고 있습니다...');
  end;
end;

procedure Tfrmmain.setimgview321Cursor(Cursor:TCursor);
begin
  if loadingtimer.Enabled then
    imgview321.Cursor:=crHourGlass
  else
    imgview321.Cursor:=Cursor;
end;

procedure Tfrmmain.N59Click(Sender: TObject);
var
  frmPrint1:TfrmPrint;
  ls:tlistitem;
  PThumbImage1:PThumbImage;
  printdata:Pprintdata;
begin
  frmPrint1:=TfrmPrint.Create(self);
  try
    Screen.Cursor:=crHourGlass;
    try
      ls:=ListView1.GetNextItem(nil, sdAll, [isSelected]);
      while ls<>nil do begin
         PThumbImage1:=PThumbImage(ls.Data);
         if (PThumbImage1.imagetype=itfile) or (PThumbImage1.imagetype=itbig) or
           (PThumbImage1.imagetype=iterror) then begin
           new(printdata);
           printdata.name:=PThumbImage1.name;
           printdata.bitmap:=nil;
           frmprint1.srclist.Add(printdata);
         end;
        ls:=ListView1.GetNextItem(ls, sdAll, [isSelected]);
      end;
    finally
     Screen.Cursor:=crdefault;
    end;
    if frmprint1.srclist.Count=0 then begin
      MessageDlg('인쇄할 파일이 없습니다.',mterror, [mbOk], 0);
      exit;
    end;
    frmprint1.ShowModal;
  finally
    frmprint1.Free;
  end;
end;

end.


