首页
社区
课程
招聘
[原创]增加你的记事本--给记事本加上文本预览功能
发表于: 2010-4-30 17:41 25257

[原创]增加你的记事本--给记事本加上文本预览功能

2010-4-30 17:41
25257

增加你的记事本--给记事本加上文本预览功能
现在记事本是越来越鸡肋了,随便找个文本编辑器都能把它给替代了,为了增加记事本在我的硬盘上的存活时间,我决定给它增加点特色功能。现在PHOTOSHOP等图形处理软件都能在图像预览,不妨我也给记事本加上个文本预览...

一般的打开/保存文件对话框是这样的(图1):

再看记事本的打开/保存文件对话框(图2):

多了一个编码的选项。这说明记事本定制了模板。在OPENFILENAME结构中:
Flags        字段如果指明OFN_ENABLEHOOK|OFN_ENABLETEMPLATE这两个选项则可以自行定制文件对话框的行为,包括消息处理等操作。
lpfnHook        字段指向的是消息处理的过程。
思路:
明白了上面这两点,思路就明确了,我们在lpfnHook指向的过程中找到处理WM_NOTIFY消息的地方,在记事本处理这个消息之前先跳转到我们事先准备好的流程中,在我们自己的流程里面进行文本预览的操作,完成之后再跳回去让记事本继续处理,这样就完成了整个过程。

操作流程:

1.先找到lpfnHook指向的过程地址。OD载入记事本(建议先从系统目录复制一份出来再进行操作,以防不测),在命令行插件中下断点:bp GetOpenFileNameW (记事本是用UNICODE方式编译的,断这个API就行了),F9运行记事本,用记事本打开一个文件。会在浏览文件的时候被OD断在系统领空。这时查看堆栈窗口,数据如下:

0007FB48   01002D89  /CALL 到 GetOpenFileNameW 来自 NOTEPAD.01002D83
0007FB4C   0100A680  \pOpenFileName = NOTEPAD.0100A680
01002D3D  |.  68 80A60001   push    0100A680                         ; /pOpenFileName = NOTEPAD.0100A680
01002D42  |.  A3 B0A60001   mov     dword ptr [100A6B0], eax         ; |
01002D47  |.  C705 8CA60001>mov     dword ptr [100A68C], 0100A5E0    ; |
01002D51  |.  C705 BCA60001>mov     dword ptr [100A6BC], 010013C4    ; |UNICODE "txt"
01002D5B  |.  C705 B4A60001>mov     dword ptr [100A6B4], 881064      ; |
01002D65  |.  C705 98A60001>mov     dword ptr [100A698], 1           ; |
01002D6F  |.  C705 C8A60001>mov     dword ptr [100A6C8], 010013A0    ; |UNICODE "NpEncodingDialog"
01002D79  |.  C705 C4A60001>mov     dword ptr [100A6C4], 01002452    ; |
01002D83  |.  FF15 D8120001 call    dword ptr [<&comdlg32.GetOpenFil>; \GetOpenFileNameW
01002D89  |.  85C0          test    eax, eax
01002D3D  |.  68 80A60001   push    0100A680 
01002D79  |.  C705 C4A60001>mov     dword ptr [100A6C4], 01002452    ; |
010025EB  |> \817F 08 A6FDF>cmp     dword ptr [edi+8], -25A          ;  Case 4E (WM_NOTIFY) of switch 0100246C
010025F2  |.  0F85 01010000 jnz     010026F9
010025F8  |.  8D85 F4FDFFFF lea     eax, dword ptr [ebp-20C]
BOOL NEAR CALLBACK HandleNotify(HWND hDlg,LPOFNOTIFY pofn)
{
	WCHAR wsFilePath[MAX_PATH] = {0};
	WCHAR	wsFileTitle[MAX_FNAME_LEN] = {0};
	
	switch(pofn->hdr.code)
	{
	case CDN_SELCHANGE: //文件名选择更改消息
		{
			CommDlg_OpenSave_GetFilePath(GetParent(hDlg), wsFilePath, MAX_PATH);	//获取选择的文件名(完整路径名称)
			
			GetFileTitle(wsFilePath, wsFileTitle, MAX_FNAME_LEN);
			SetDlgItemText(hDlg, IDC_ST_FILENAME, wsFileTitle);
			
			DWORD	dwFileAttr	=	GetFileAttributes(wsFilePath);
			
			if (!(dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))	//如果选中的是文件
			{
				
				
				BY_HANDLE_FILE_INFORMATION	stFileInfo;
				HANDLE	hFile	=	CreateFile(wsFilePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
				GetFileInformationByHandle(hFile, &stFileInfo);
				DWORD	dwMapSize	=	stFileInfo.nFileSizeLow > 1024?1024:stFileInfo.nFileSizeLow;

				if (!dwMapSize)	//如果文件大小为零
				{
					SetDlgItemText(hDlg, IDC_EDTPREV, TEXT(""));
					break;
				}

				HANDLE	hFileMap	=	CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwMapSize, NULL);
				CloseHandle(hFile);
				LPWSTR	lpVoid	=	(LPWSTR)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, dwMapSize);
				CloseHandle(hFileMap);
				LPSTR	lpMem;
				INT	nCount;
				
				if (0xFEFF	==	lpVoid[0])	//如果是UNICODE文本文件
				{
					nCount	=	WideCharToMultiByte(CP_ACP, 0, lpVoid + 1, dwMapSize/sizeof(WCHAR) - 1, NULL, 0, NULL, NULL);
					lpMem	=	(LPSTR)VirtualAlloc(NULL, nCount + 1, MEM_COMMIT, PAGE_READWRITE);
					WideCharToMultiByte(CP_ACP, 0, lpVoid + 1, dwMapSize/sizeof(WCHAR), lpMem, nCount, NULL, NULL);
				}
				else
				{
					nCount	=	dwMapSize + sizeof(CHAR);
					lpMem	=	(LPSTR)VirtualAlloc(NULL, nCount, MEM_COMMIT, PAGE_READWRITE);
					lpMem[nCount]	=	'\0';
					memcpy(lpMem, lpVoid, nCount);
				}
				
				UnmapViewOfFile(lpVoid);
				
				for (INT i = 0; i < (nCount - 1); i++)
				{
					if (lpMem[i] == 0)
						lpMem[i]	=	0x20;
				}
				
				SetDlgItemTextA(hDlg, IDC_EDTPREV, (LPSTR)lpMem);
				
				VirtualFree(lpMem, nCount, MEM_RELEASE);
				
			}
			else if (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY)	//如果是目录
			{
				SetDlgItemText(hDlg, IDC_EDTPREV, TEXT(""));
			}
		}
		break;
	}
	return TRUE;
}

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (33)
雪    币: 95
活跃值: (419)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
2
占座沙发,学习
2010-4-30 19:56
0
雪    币: 433
活跃值: (1895)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
3
这个功能不错,很方便。
2010-4-30 20:06
0
雪    币: 222
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
好货....ctrl+N建立一个空的新文本,现在能不能在ctrl+n后 文本上面有自己定义的文字呢
2010-4-30 21:16
0
雪    币: 234
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
很强大~记事本也可以这么玩~~
2010-5-2 19:32
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
太有才了,呵呵
2010-5-11 21:46
0
雪    币: 222
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
太厉害了,这个功能增强太好了
2010-5-14 16:33
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
只有想不到,没有做不到。
2010-5-14 16:47
0
雪    币: 146
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
这也行,不错啊!!
2010-5-15 13:52
0
雪    币: 45
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
建议预览的时候!弄个自动换行!    有的一行太长了 看还要点滚动条 太麻烦!
2010-5-15 14:12
0
雪    币: 236
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
这个非常的强大啊,偶学习了
2010-5-16 07:13
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
12
实现自动换行也简单,只要设置Edit控件的属性就可以。自己练习一下吧。
2010-5-17 10:30
0
雪    币: 6716
活跃值: (4343)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
这个功能有实用性。
2010-5-31 10:56
0
雪    币: 21
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
可惜看不懂。。。
2010-5-31 13:40
0
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
不错的文章  
2010-5-31 23:24
0
雪    币: 327
活跃值: (1723)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
很值得学习一下。
2010-6-4 16:04
0
雪    币: 77
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
这个一定要顶一下。
2010-6-4 17:27
0
雪    币: 145
活跃值: (85)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
18
我勒个去。记事本还能搞成这个样子!
2010-6-14 07:38
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
佩服佩服!!!!!!!!!!!!
2010-6-14 08:38
0
雪    币: 379
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
20
=,=
记事本已经被我抛弃了。。。现在用notepad++,不过因为插件太多,启动速度有点慢~
偶尔需要快速浏览某些文本文件的时候才会用记事本打开
2010-6-14 09:30
0
雪    币: 20
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
楼主的这个教程太好了!
最好是再做一个一是添加区段方法出来的记事本教程。
呵呵。。。
2010-6-14 09:53
0
雪    币: 145
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
22
good  very good.
2010-6-14 20:12
0
雪    币: 558
活跃值: (141)
能力值: ( LV2,RANK:16 )
在线值:
发帖
回帖
粉丝
23
很好啊。。。记事本多用途,好啊
2010-6-15 01:40
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
好强大,
2010-6-25 16:52
0
雪    币: 238
活跃值: (1095)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
直接晕菜~~一点一个几M的TXT就KO了~~预览卡一次~~~打开再卡一次~~不过探索精神值得表扬~~谢谢楼主的好帖~~~
2010-7-11 21:55
0
游客
登录 | 注册 方可回帖
返回