namespace win.ole.image;

import win;
import win.gdi
import win.guid;
import com; 
import win.ole;

IID_IPicture = win.guid();
IID_IPicture.Data1 =  2079852928 
IID_IPicture.Data2 = 48946
IID_IPicture.Data3 = 4122
IID_IPicture.Data4 = { 139;187;0;170;0;48;12;171}


/*intellisense(win.ole.image)*/ 
OleLoadPicture = ::Oleaut32.api("OleLoadPicture","int(pointer lpStream,int lSize,int fRunmode,struct riid,pointer &lpIPicture)")
OleSavePictureFile = Oleaut32.api("OleSavePictureFile","int(pointer pDisp,string szFilePath)") 
OleCreatePictureIndirect = Oleaut32.api("OleCreatePictureIndirect","int(struct lpPictDesc, struct riid, INT fOwn, pointer & lplpvObj)")
/*end intellisense*/

var PICTDESC = class {
    INT cbSizeofstruct;
    INT picType;
    union desc = {
        struct bmp = {
            pointer hbitmap;        // Bitmap
            INT hpal;           // Accompanying palette
        } 

        struct wmf = {
            pointer hmeta;          // Metafile
            int xExt;
            int yExt;           // Extent
        } 

        struct icon ={
            pointer hicon;              // Icon
        } ;
 
        struct emf = {
            int hemf;        // Enhanced Metafile
        } 
    };

}  

 

/*封装IPicture{{*/
	var copyHandle = function(){   
		if( owner.Type ==  3 )
			return  ::CopyImage(   topointer(  owner.Handle  ) , 0x1/*_IMAGE_ICON*/, 0, 0, 0x4/*_LR_COPYRETURNORG*/) , 0x1/*_IMAGE_ICON*/;
  		else if( owner.Type ==  1 )
  	  		return  ::CopyImage(   topointer(  owner.Handle  ) , 0/*_IMAGE_BITMAP*/, 0, 0, 0x4/*_LR_COPYRETURNORG*/) , 0/*_IMAGE_BITMAP*/;
	}
	var save = function( filepath ){    
		OleSavePictureFile( ..com.topointer( owner ) ,::SysAllocString( ..string.toUnicode( ..io.fullpath( filepath) ) ) ) ;  
	}
	var wrap = function(ipicture){
		ipicture.Save = save
		ipicture.CopyHandle = copyHandle
	}
/*}}*/

load = function(strfile){  
    var strBmp = "";
    if( #strfile < 0x104/*::_MAX_PATH*/ ){ //是文件路径吗？
	    strBmp = ..string.load( ..io.fullpath( strfile ) ) //尝试载入图像文件
	    if( !strBmp )
	        strBmp = strfile;
    }
	else{
	    strBmp = strfile;
	}
	
	var hImageMemory= ::GlobalAlloc( 0x2 /*_GMEM_MOVEABLE*/, #strBmp); //给图片分配全局内存
	pImageMemory=::GlobalLock(hImageMemory); //锁定内存
	
	
	::CopyMemory(pImageMemory,strBmp,#strBmp);//复制图片
	::GlobalUnlock(hImageMemory); //解锁内存
 	
	var pIStream  ;//创建一个IStream接口指针，用来保存图片流
	var pIPicture ;//创建一个IPicture接口指针，表示图片对象
	var re ;
	
	re,pIStream = ::CreateStreamOnHGlobal(hImageMemory, 1,pIStream) //用全局内存初使化IStream接口指针
	if(re)return; //不等于0为出错
	
	re,pIPicture =  OleLoadPicture(pIStream, #strBmp, 0, IID_IPicture, pIPicture  );//用OleLoadPicture获得IPicture接口指针
	if(re)return; //不等于0为出错c
	
	..com.Release(pIStream) //释放pIStream
	::GlobalFree(hImageMemory); //释放全局内存
	
 	
	var pic = ..com.QueryObject( pIPicture  ,IID_IPicture ) //将一个 C指针转换为com object
	..com.Release(pIPicture)
 	
 	wrap(pic);
	return  pic; 
}



snap = function(hWnd)   {
 
	hWnd := ..win.getDesktop()
	
	var re ,rcWindow = ::GetWindowRect(hWnd,::RECT() )
	var wndWidth = rcWindow.right - rcWindow.left
	var wndHeight = rcWindow.bottom - rcWindow.top

	//get window's device context
	var hSrcDC = ::GetWindowDC(hWnd)
	
	//create a compatible DC
	var hDCMemory  = ::CreateCompatibleDC(hSrcDC)
	
	//create a memory bitmap in the DC just created
	//he has the size of the window we're capturing
	var tempPict = ::CreateCompatibleBitmap(hSrcDC, wndWidth, wndHeight)
	var oldPict = ::SelectObject(hDCMemory , tempPict)
  
	//copy the screen image into the DC
	::BitBlt( hDCMemory , 0, 0, wndWidth, wndHeight, hSrcDC, 0, 0,0xCC0020/*_SRCCOPY*/)
		// set the old DC image and release the DC
	tempPict = ::SelectObject(hDCMemory , oldPict)
	::DeleteDC( hDCMemory  )
	::ReleaseDC(hWnd, hSrcDC)
	
	//fill the ScreenPic structure
	var picdesc =PICTDESC()
	picdesc.cbSizeofstruct = ..raw.sizeof( picdesc );
	picdesc.desc.bmp.hbitmap = tempPict;
	picdesc.picType = 0x1/*_PICTYPE_BITMAP*/;
	 
	//convert the image to a IpictureDisp object
	// create the picture,
	// return an object reference right into the function result
	var re ,pIPicture  =OleCreatePictureIndirect( picdesc, IID_IPicture, 1, pIPicture); 
	
	var pic = ..com.QueryObject( pIPicture  ,IID_IPicture ) //将一个 C指针转换为com object 
	..com.Release(pIPicture) 
	 
	wrap(pic);
	return pic;
} 

 

self.type = {
	none = 0;
	uninitialized = -1;
	bitmap = 1;
	metafile = 2;
	icon = 3;
	enhmetafile = 4;
}

 /**intellisense()
_PICTYPE_UNINITIALIZED=@0xFFFFFFFF/*_PICTYPE_UNINITIALIZED*/
_PICTYPE_NONE=@0x0/*_PICTYPE_NONE*/
_PICTYPE_BITMAP=@0x1/*_PICTYPE_BITMAP*/
_PICTYPE_METAFILE=@0x2/*_PICTYPE_METAFILE*/
_PICTYPE_ICON=@0x3/*_PICTYPE_ICON*/
_PICTYPE_ENHMETAFILE=@0x4/*_PICTYPE_ENHMETAFILE*/
end intellisense**/
 
/**intellisense(win.ole.image) 
load(__/*请输入文件路径*/) =  载入图片文件返回IPicture(com对象)
snap(__/*指定窗口句柄\n默认为桌面窗口*/) = 抓屏并返回IPicture(com对象) 
end intellisense**/
 
/**intellisense()  
!ipicture.Handle = 位图句柄
!ipicture.Type = 图片类型\n参考win.ole.image.type成员
!ipicture.Save(__/*文件路径*/) = 保存图片到文件
!ipicture.CopyHandle() = 返回位图句柄,位图类型(_IMAGE_BITMAP 或 _IMAGE_ICON)
?win.ole.image.snap = !ipicture.
?win.ole.image.load = !ipicture.
end intellisense**/

 