#include <windows.h>
#include <shlwapi.h>
#pragma intrinsic(memset)
#define elemof(x) (sizeof(x)/sizeof(*(x)))
#define T(x) TEXT(x)
#if _MSC_VER < 1400 // Visual C++ 6
__forceinline void __stosd(void*p, DWORD val, DWORD count) {
_asm mov edi,p
_asm mov eax,val
_asm mov ecx,count
_asm rep stosd
}
#endif
struct RECTS{
short left,top,right,bottom;
};
#pragma pack(2)
union PMF{ // Placeable Metafile Header, 22 Bytes
struct{
DWORD key;
WORD hmf;
RECTS bbox;
WORD inch;
DWORD reserved;
WORD checksum;
};
WORD xorwords[10]; // not including checksum
};
#pragma pack()
static int vMBox(UINT id, UINT uType, va_list va) {
TCHAR s[256],t[256];
LoadString(0,id,t,elemof(t));
wvnsprintf(s,elemof(s),t,va);
#ifdef _DEBUG
if (id<16) {
StrCatBuff(s,T("\r\n"),elemof(s));
OutputDebugString(s);
return IDOK;
}
#endif
return MessageBox(0,s,T("wmfsave"),uType);
}
static int _cdecl MBox(UINT id, UINT type, ...) {
va_list va;
va_start(va,type);
return vMBox(id,type,va);
}
// Remove META_ESCAPE records (inserted by MSDRAW)
static BOOL CALLBACK EnumProc(HDC dc, HANDLETABLE*ht, METARECORD*mr, int cObj, LPARAM lParam) {
#ifdef _DEBUG
MBox(3,MB_OK,mr->rdSize,mr->rdFunction,mr->rdParm[0],mr->rdParm[1],mr->rdParm[2],mr->rdParm[3]);
#endif
if (mr->rdFunction!=META_ESCAPE) PlayMetaFileRecord(dc,ht,mr,cObj);
return TRUE;
}
EXTERN_C void WinMainCRTStartup() {
// Check presence of CF_METAFILEPICT at startup
for(;;){
OpenClipboard(0);
HANDLE clip=GetClipboardData(CF_METAFILEPICT);
CloseClipboard();
if (!clip) switch (MBox(19,MB_ICONQUESTION|MB_CANCELTRYCONTINUE)) {
case IDCANCEL: ExitProcess(IDCANCEL);
case IDTRYAGAIN: continue;
}
break;
}
PMF pmf;
ZeroMemory(&pmf,sizeof pmf);
// Prepare a SaveFile dialog with defaults
OPENFILENAME ofn;
__stosd((DWORD*)&ofn,0,sizeof ofn/4);
ofn.lStructSize=sizeof ofn;
TCHAR fname[MAX_PATH],sFilter[64];
lstrcpyn(fname,PathGetArgs(GetCommandLine()),elemof(fname));
sFilter[LoadString(0,16,sFilter,elemof(sFilter)-1)+1]=0;
ofn.lpstrFilter=sFilter;
ofn.lpstrFile=fname;
ofn.nMaxFile=elemof(fname);
ofn.Flags=OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY;
// Get file name for save
while (GetSaveFileName(&ofn)) {
// Re-check presence of CF_METAFILEPICT
OpenClipboard(0);
HANDLE clip=GetClipboardData(CF_METAFILEPICT);
pmf.key=0x9AC6CDD7;
HDC dc=CreateIC(T("DISPLAY"),NULL,NULL,NULL);
pmf.inch=GetDeviceCaps(dc,LOGPIXELSX);
DeleteDC(dc);
if (clip) {
METAFILEPICT*mfp=(METAFILEPICT*)GlobalLock(clip);
#ifdef _DEBUG
vMBox(2,MB_OK,(va_list)mfp);
#endif
dc=CreateMetaFile(NULL);
EnumMetaFile(dc,mfp->hMF,EnumProc,NULL);
HMETAFILE hmf=CloseMetaFile(dc);
UINT metasize=GetMetaFileBitsEx(hmf,0,NULL);
void*metabits=GlobalAlloc(LPTR,metasize);
GetMetaFileBitsEx(hmf,metasize,metabits);
pmf.bbox.right=(short)mfp->xExt;
pmf.bbox.bottom=(short)mfp->yExt;
switch (mfp->mm) {
case MM_LOMETRIC: pmf.inch=254; break; //10 Punkte pro mm = 254 pro Zoll
case MM_HIMETRIC: pmf.inch=2540; break; //100 Punkte pro mm = 2540 pro Zoll
case MM_LOENGLISH: pmf.inch=100; break; //100 Punkte pro Zoll
case MM_HIENGLISH: pmf.inch=1000; break; //1000 Punkte pro Zoll
case MM_TWIPS: pmf.inch=1440; break; //1/20 von 1/72 Zoll = 1440 pro Zoll
case MM_ANISOTROPIC: //WinWord...???
case MM_ISOTROPIC: pmf.inch=MulDiv(pmf.inch,254,10); break;
}
pmf.checksum=0;
for (int i=0; i<elemof(pmf.xorwords); i++) pmf.checksum^=pmf.xorwords[i];
GlobalUnlock(clip);
HANDLE hf=CreateFile(fname,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
DWORD bw;
bool success = false;
if (hf!=INVALID_HANDLE_VALUE) {
success=WriteFile(hf,&pmf,sizeof pmf,&bw,NULL) && bw==sizeof pmf
&& WriteFile(hf,metabits,metasize,&bw,NULL) && bw==metasize;
if (!CloseHandle(hf)) success=false;
}
GlobalFree(metabits);
if (MBox(success?18:17,MB_ICONQUESTION|MB_YESNO,GetLastError())!=IDYES) break; // ask for another picture
}else MBox(19,MB_ICONASTERISK);
CloseClipboard();
}
ExitProcess(0);
}
Detected encoding: ASCII (7 bit) | 2
|