{

   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 Umain;

interface

uses
  Windows, classes, CustomContextMenu, SysUtils, dialogs, clipbrd,
  graphics, FreeBitmap, FreeImage, FreeUtils, ImgList,
  registry, Udatamodule, shlobj;

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

type
  TMyContextMenu = class(TOwnerDrawContextMenu)
  public
    // Basic methods
    function GetHelpText(IdCmdOffset: UINT): String; override;
    function GetVerb(IdCmdOffset: UINT): String; override;
    function AddMenuItems(Menu: HMENU; MenuIndex, IdCmdFirst, IdCmdLast: UINT): UINT; override;
    procedure ExecuteCommand(IdCmdOffset: UINT); override;
    // Owner-draw methods
    procedure MeasureMenuItem(IdCmd: UINT; var Width: UINT; var Height: UINT); override;
    procedure DrawMenuItem(Menu: HMENU; IdCmd: UINT; DC: HDC; Rect: TRect;
      State: TOwnerDrawState); override;

    destructor Destroy; override;
  private
    previewid,previewwidth,previewheight:integer;
    subid:integer;
    subtitle:string;
    previewbmp:tbitmap;
    DataModule1:TDataModule1;

    procedure proc_wallpaper(method:integer;filename:string);
  end;

const
  GUID_ContextMenuEntry: TGUID = '{1EC8B7CE-BB7B-4108-B74C-6DB37FF99274}';
  VERB = 'nView Shellmenu';
  thumbsize = 125;
  thumbmargin = 10;

implementation
uses Ufunction, Uregistry, Ufrmoption, shellapi;

function TMyContextMenu.GetHelpText(IdCmdOffset: UINT): String;
begin
  Result := '';
end;

function TMyContextMenu.GetVerb(IdCmdOffset: UINT): String;
begin
  Result := VERB;
end;

procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor;
  Width: Integer);

  procedure DoRect;
  var
    TopRight, BottomLeft: TPoint;
  begin
    with Canvas, Rect do
    begin
      TopRight.X := Right;
      TopRight.Y := Top;
      BottomLeft.X := Left;
      BottomLeft.Y := Bottom;
      Pen.Color := TopColor;
      PolyLine([BottomLeft, TopLeft, TopRight]);
      Pen.Color := BottomColor;
      Dec(BottomLeft.X);
      PolyLine([TopRight, BottomRight, BottomLeft]);
    end;
  end;

begin
  Canvas.Pen.Width := 1;
  Dec(Rect.Bottom); Dec(Rect.Right);
  while Width > 0 do
  begin
    Dec(Width);
    DoRect;
    InflateRect(Rect, -1, -1);
  end;
  Inc(Rect.Bottom); Inc(Rect.Right);
end;

function TMyContextMenu.AddMenuItems(Menu: HMENU; MenuIndex, IdCmdFirst, IdCmdLast: UINT): UINT;
var
  miInfo:TMenuItemInfo;
  popMenu:HMenu;

  exts,s1:string;
  FBitmap:TFreeWinBitmap;
  w,h:integer;
  NewWidth,NewHeight:integer;
  r1:trect;
  thumbsize:cardinal;
  fif:FREE_IMAGE_FORMAT;
  os:integer;

  procedure addmenu(targetmenu:HMENU;id:integer;caption:string);
  begin
    FillChar(miInfo, SizeOf(miInfo), 0);
    with miInfo do begin
      cbSize := SizeOf(MenuItemInfo);
      fMask := MIIM_TYPE or MIIM_ID;
      fType := MFT_STRING;
      fState := MFS_ENABLED;
      wID := id;
      dwTypeData := PChar(caption);
      cch := Length(caption);
    end;
    InsertMenuItem(targetmenu, 0, TRUE, miInfo);
  end;

  procedure addseperate(targetmenu:HMENU;id:integer);
  begin
    FillChar(miInfo, SizeOf(miInfo), 0);
    with miInfo do begin
      cbSize := SizeOf(MenuItemInfo);
      fMask := MIIM_TYPE or MIIM_ID;
      fType := MFT_SEPARATOR;
      fState := MFS_ENABLED;
      wID := id;
    end;
    InsertMenuItem(targetmenu, 0, TRUE, miInfo);
  end;
begin
try
  result:=0;

  if FileNames.Count<>1 then exit;
  exts:=lowercase(FIU_GetFullExtList)+';';
  s1:=lowercase(ExtractFileExt(FileNames.Strings[0]));
  if pos('*'+s1+';',exts)=0 then exit;

  if RegGetDWORD(HKEY_CURRENT_USER, 'software\'+thisregname+'\shellmenu\thumbsize', thumbsize)=false then
    thumbsize:=125;
  if (thumbsize<0) or (thumbsize>300) then thumbsize:=300;

  FBitmap:=TFreeWinBitmap.Create;
  try
   try
    FBitmap.Load2(FileNames.Strings[0],fif);
    w:=FBitmap.GetWidth;
    h:=FBitmap.GetHeight;
    subtitle:=format('(%d x %d) %d bit (%s)',[w,h,FBitmap.GetBitsPerPixel,trim(FreeImage_GetFormatFromFIF(fif))]);

    if FBitmap.IsTransparent then
      FBitmap.SetTransparentBg(nil);

    if w > h then begin
      NewWidth:=thumbsize;
      NewHeight:=Round(thumbsize * h / w);
    end else begin
      NewWidth:=Round(thumbsize * w / h);
      NewHeight:=thumbsize;
    end;
    if NewWidth > w then NewWidth:=w;
    if NewHeight > h then NewHeight:=h;

    FBitmap.MakeThumbnail(NewWidth,NewHeight,FBitmap,false,thumbsize);
    FBitmap.ConvertTo24Bits;

    if assigned(previewbmp) then freeandnil(previewbmp);
    previewbmp:=tbitmap.Create;
    with previewbmp do begin
      PixelFormat := pf24bit;
      Width := NewWidth;
      Height := NewHeight;
      Canvas.Lock;
      FBitmap.Draw(Canvas.Handle, rect(0,0,NewWidth,NewHeight));
      r1:=rect(0,0,width,height);
      Frame3D(Canvas,r1,clBtnShadow,clBtnHighlight,1);
      Canvas.Unlock;
    end;

    previewwidth:=NewWidth;
    previewheight:=NewHeight;
   except
   end;
  finally
    FBitmap.Free;
  end;

  FillChar(miInfo, SizeOf(miInfo), 0);
  miInfo.cbSize := SizeOf(miInfo);
  miInfo.fMask := MIIM_ID or MIIM_TYPE;
  miInfo.fType := MFT_OWNERDRAW;
  miInfo.fState := MFS_ENABLED;
  miInfo.dwTypeData:= pchar('preview');
  miInfo.cch:= length('preview');
  miInfo.wID := IdCmdFirst+1;
  previewid:= IdCmdFirst+1;
  InsertMenuItem(Menu, MenuIndex, True, miInfo);

  //서브메뉴
  popMenu := CreatePopupMenu;

  addmenu(popMenu,IdCmdFirst+2,'배경화면 늘리기');
  addmenu(popMenu,IdCmdFirst+3,'배경화면 바둑판');
  addmenu(popMenu,IdCmdFirst+4,'배경화면 가운데');
  addseperate(popMenu,IdCmdFirst+5);
  addmenu(popMenu,IdCmdFirst+6,'미리보기 크기 설정');
  addmenu(popMenu,IdCmdFirst+7,'nView로 열기');

  os:=GetOperatingSystem;
  if (os>=cOsXP) and (os<=cOsVista) then begin
    FillChar(miInfo, SizeOf(miInfo), 0);
    miInfo.cbSize := SizeOf(miInfo);
    miInfo.fMask := MIIM_SUBMENU or MIIM_ID or MIIM_TYPE;
    miInfo.fType := MFT_OWNERDRAW;
    miInfo.wID := IdCmdFirst+7;
    subid:= IdCmdFirst+7;
    miInfo.dwTypeData := nil;
    miInfo.cch := 0;
    miInfo.hSubMenu := popMenu;
    InsertMenuItem(Menu, MenuIndex, True, miInfo);
  end else begin
    InsertMenu(Menu, MenuIndex, MF_BYPOSITION or MF_POPUP, popMenu, pchar(subtitle));
  end;

  result := IdCmdFirst+7;
except
end;
end;

procedure TMyContextMenu.ExecuteCommand(IdCmdOffset: UINT);
var
  s:string;
  frmoption:Tfrmoption;
begin
try
  case IdCmdOffset of
    1,7:begin
      s:=GetModuleDir+'nView.exe';
      if sysutils.FileExists(s) then begin
        s:=format('"%s" "%s"',[s,FileNames[0]]);
        ExecuteFile(s,true);
      end;
    end;
    2: proc_wallpaper(3,FileNames[0]);
    3: proc_wallpaper(2,FileNames[0]);
    4: proc_wallpaper(1,FileNames[0]);
    6:begin
      frmoption:=Tfrmoption.Create(nil, GetForegroundWindow);
      frmoption.Caption:='nView 미리보기 설정';
      frmoption.ShowModal;
      frmoption.Free;
    end;
  end;
except
end;
end;

procedure TMyContextMenu.MeasureMenuItem(IdCmd: UINT; var Width: UINT; var Height: UINT);
begin
try
  if IdCmd=previewid then begin
    Width:=previewwidth+thumbmargin;
    Height:=previewheight+thumbmargin;

  end else if IdCmd=subid then begin
    width:=GetStandardTextWidth(subtitle)+16;
    height:=GetStandardMenuItemHeight;

  end;
except
end;
end;

procedure TMyContextMenu.DrawMenuItem(Menu: HMENU; IdCmd: UINT; DC: HDC; Rect: TRect;
  State: TOwnerDrawState);
var
  x,y:integer;
  Bmp:Tbitmap;
  font,oldfont:HFONT;
begin
try
  if odSelected in State then
  begin
    SetBkColor(DC, GetSysColor(COLOR_HIGHLIGHT));
    SetTextColor(DC, GetSysColor(COLOR_HIGHLIGHTTEXT));
    FillRect(DC, Rect, HBRUSH(COLOR_HIGHLIGHT+1));
  end
  else
  begin
    SetBkColor(DC, GetSysColor(COLOR_MENU));
    SetTextColor(DC, GetSysColor(COLOR_MENUTEXT));
    FillRect(DC, Rect, HBRUSH(COLOR_MENU+1));
  end;

  if (IdCmd=previewid) and assigned(previewbmp) then begin
    x:=((rect.Right-rect.Left) div 2)-(previewwidth div 2);
    y:=Rect.Top+(thumbmargin div 2);
    BitBlt(DC,
         x,y,previewwidth,previewheight,
         previewbmp.Canvas.Handle,0,0, SRCCOPY);

  end else if IdCmd=subid then begin
    if DataModule1=nil then
      DataModule1:=TDataModule1.Create(nil);

    Bmp:=tbitmap.Create;
    try
      DataModule1.ImageList1.GetBitmap(0,bmp);
      bmp.PixelFormat:=pf8bit;
      DrawTransparentBitmap(DC, Bmp.Handle, Rect.Left, Rect.Top, clwhite);

      font:=CreateFont(Rect.Bottom-Rect.Top-5,
           0,0,0,0,0,0,0,HANGEUL_CHARSET,0,0,0,0,'굴림');
  		oldfont:=SelectObject(DC,font);
      TextOut(DC, Rect.Left+16+2, Rect.Top+1, PChar(subtitle), Length(subtitle));
      SelectObject(DC,oldfont);
   		DeleteObject(font);

{
      bmp.Width:=200;
      if odSelected in State then
        bmp.Canvas.Font.Color:=GetSysColor(COLOR_HIGHLIGHTTEXT)
      else
        bmp.Canvas.Font.Color:=GetSysColor(COLOR_MENUTEXT);
      bmp.Canvas.Font.Size:=10;
      bmp.Canvas.Font.Style:=[fsbold];
      bmp.Canvas.TextOut(Rect.Left+24,4,subtitle);
      DrawTransparentBitmap(DC, Bmp.Handle, Rect.Left, Rect.Top, clwhite);
}
    finally
      bmp.Free;
    end;
  end;
except
end;
end;


procedure TMyContextMenu.proc_wallpaper(method:integer;filename:string);
var
  reg: TRegIniFile;
  tfilename:string;
  FBitmap:TFreeWinBitmap;
begin
try
  FBitmap:=TFreeWinBitmap.Create;
  try
    try
      FBitmap.Load(filename);
//      tfilename:=GetWindowsDir+'nView 배경화면.bmp';
      tfilename:=GetShellPath(CSIDL_APPDATA)+thisregname;
      sysutils.ForceDirectories(tfilename);
      tfilename:=tfilename+'\nView 배경화면.bmp';
      FBitmap.Save(tfilename);
    except
      on E: Exception do begin
        MessageDlg(E.Message,mtError, [mbOk], 0);
        exit;
      end;
    end;
  finally
    FBitmap.Free;
  end;

  reg := TRegIniFile.Create('Control Panel\Desktop');
  try
    with reg do
    begin
      WriteString('', 'Wallpaper', tfilename);
      case method 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);
except
end;
end;

destructor TMyContextMenu.Destroy;
begin
try
  freeandnil(previewbmp);
  if DataModule1<>nil then freeandnil(DataModule1);
except
end;
  inherited;
end;

initialization
  Initialize(TMyContextMenu, GUID_ContextMenuEntry, 'nView Shellmenu');

finalization

end.

