类似 Rolan 的快速启动工具。
启动后隐藏,当鼠标移至左上角时,窗口显示,点击项目可运行程序。
GitHub地址: MyRolan 。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #if defined(UNICODE) && !defined(_UNICODE) 2 #define _UNICODE 3 #elif defined(_UNICODE) && !defined(UNICODE) 4 #define UNICODE 5 #endif 6 7 #include <tchar.h> 8 #include <windows.h> 9 #include <string> 10 #include <stdio.h> 11 #include <shellapi.h> 12 #include <windowsx.h> 13 #include <commctrl.h> 14 using namespace std; 15 16 /* Declare Windows procedure */ 17 LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); 18 19 /* Make the class name into a global variable */ 20 TCHAR szClassName[ ] = _T("MyRolan"); 21 22 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) 23 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) 24 25 typedef struct item { 26 string name; 27 string path; 28 string icon_path; 29 string arguments; 30 } item; 31 typedef struct group { 32 string name; 33 item* items; 34 int item_num; 35 } group; 36 37 int WIDTH=398; 38 int HEIGHT=500; 39 int GROUP_WIDTH=100; 40 int ITEM_WIDTH=100; 41 int ITEM_HEIGHT=40; 42 int GROUP_HEIGHT=ITEM_HEIGHT; 43 #define BKCOLOR RGB(240,240,240) 44 #define COMMON_ITEM_BKCOLOR RGB(220,220,220) 45 #define ACTIVE_ITEM_BKCOLOR RGB(200,200,200) 46 47 48 group* groups; 49 int group_num; 50 int current_group=0; 51 int current_item=0; 52 int current_top=0; 53 int item_columns=3; 54 55 56 57 int WINAPI WinMain (HINSTANCE hThisInstance, 58 HINSTANCE hPrevInstance, 59 LPSTR lpszArgument, 60 int nCmdShow) 61 { 62 HWND hwnd; /* This is the handle for our window */ 63 MSG messages; /* Here messages to the application are saved */ 64 WNDCLASSEX wincl; /* Data structure for the windowclass */ 65 66 /* The Window structure */ 67 wincl.hInstance = hThisInstance; 68 wincl.lpszClassName = szClassName; 69 wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ 70 wincl.style = CS_DBLCLKS; /* Catch double-clicks */ 71 wincl.cbSize = sizeof (WNDCLASSEX); 72 73 /* Use default icon and mouse-pointer */ 74 wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); 75 wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); 76 wincl.hCursor = LoadCursor (NULL, IDC_ARROW); 77 wincl.lpszMenuName = NULL; /* No menu */ 78 wincl.cbClsExtra = 0; /* No extra bytes after the window class */ 79 wincl.cbWndExtra = 0; /* structure or the window instance */ 80 /* Use Windows's default colour as the background of the window */ 81 //wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; 82 wincl.hbrBackground = NULL; 83 /* Register the window class, and if it fails quit the program */ 84 if (!RegisterClassEx (&wincl)) 85 return 0; 86 87 /* The class is registered, let's create the program*/ 88 hwnd = CreateWindowEx ( 89 WS_EX_TOOLWINDOW, /* Extended possibilites for variation */ 90 szClassName, /* Classname */ 91 _T("MyRolan"), /* Title Text */ 92 WS_EX_TOOLWINDOW, /* default window WS_OVERLAPPEDWINDOW*/ 93 CW_USEDEFAULT, /* Windows decides the position */ 94 CW_USEDEFAULT, /* where the window ends up on the screen */ 95 WIDTH, /* The programs width */ 96 HEIGHT, /* and height in pixels */ 97 HWND_DESKTOP, /* The window is a child-window to desktop */ 98 NULL, /* No menu */ 99 hThisInstance, /* Program Instance handler */ 100 NULL /* No Window Creation data */ 101 ); 102 DWORD dwExStyle = GetWindowLong(hwnd, GWL_STYLE); 103 dwExStyle &=~WS_CAPTION; 104 SetWindowLong(hwnd, GWL_STYLE, dwExStyle); 105 106 /* Make the window visible on the screen */ 107 ShowWindow (hwnd, nCmdShow); 108 109 /* Run the message loop. It will run until GetMessage() returns 0 */ 110 while (GetMessage (&messages, NULL, 0, 0)) 111 { 112 /* Translate virtual-key messages into character messages */ 113 TranslateMessage(&messages); 114 /* Send message to WindowProcedure */ 115 DispatchMessage(&messages); 116 } 117 118 /* The program return-value is 0 - The value that PostQuitMessage() gave */ 119 return messages.wParam; 120 } 121 void remove_nextline(char* buf) { 122 int l=strlen(buf); 123 if(buf[l-1]=='\n') 124 buf[l-1]='\0'; 125 } 126 int load_data(HWND hwnd) { 127 FILE* f=fopen("data.txt","r"); 128 if(f==NULL) { 129 MessageBox(hwnd,"Data File Not Exist.","Error!",0); 130 return -1; 131 } 132 char buf[500]; 133 fgets(buf,500,f); 134 sscanf(buf,"%d",&group_num); 135 groups=new group[group_num]; 136 for(int i=0; i<group_num; i++) { 137 fgets(buf,500,f); 138 remove_nextline(buf); 139 groups[i].name=buf; 140 fgets(buf,500,f); 141 sscanf(buf,"%d",&groups[i].item_num); 142 groups[i].items=new item[groups[i].item_num]; 143 for(int j=0; j<groups[i].item_num; j++) { 144 fgets(buf,500,f); 145 remove_nextline(buf); 146 groups[i].items[j].name=buf; 147 fgets(buf,500,f); 148 remove_nextline(buf); 149 groups[i].items[j].path=buf; 150 fgets(buf,500,f); 151 remove_nextline(buf); 152 groups[i].items[j].icon_path=buf; 153 fgets(buf,500,f); 154 remove_nextline(buf); 155 groups[i].items[j].arguments=buf; 156 } 157 } 158 fclose(f); 159 return 0; 160 } 161 long get_rect_width(RECT rect) { 162 return rect.right-rect.left; 163 } 164 165 long get_rect_height(RECT rect) { 166 return rect.bottom-rect.top; 167 } 168 long get_client_width(HWND hwnd) { 169 RECT rect; 170 GetClientRect (hwnd, &rect) ; 171 return get_rect_width(rect); 172 } 173 174 long get_client_height(HWND hwnd) { 175 RECT rect; 176 GetClientRect (hwnd, &rect) ; 177 return get_rect_height(rect); 178 } 179 int xy_to_num(int num,int columns,int width,int height,int x,int y) { 180 int c=x/width; 181 if(c>=columns)return -1; 182 int r=y/height; 183 int n=columns*r+c; 184 if(n>=num)return -1; 185 return n; 186 } 187 POINT get_client_mouse(HWND hwnd) { 188 POINT mouse; 189 GetCursorPos(&mouse);//获取鼠标的屏幕坐标 190 ScreenToClient(hwnd,&mouse);//转换为界面坐标 191 return mouse; 192 } 193 int get_current_position(HWND hwnd,int& is_group) { 194 POINT mouse=get_client_mouse(hwnd); 195 if(mouse.x<0||mouse.x>WIDTH||mouse.y<0||mouse.y>HEIGHT)return -1; 196 if(mouse.x<=GROUP_WIDTH) { 197 is_group=1; 198 int n=xy_to_num(group_num,1,GROUP_WIDTH,GROUP_HEIGHT,mouse.x,mouse.y); 199 return n; 200 } 201 is_group=0; 202 int num=groups[current_group].item_num; 203 int n=xy_to_num(num,item_columns,ITEM_WIDTH,ITEM_HEIGHT,mouse.x-GROUP_WIDTH,mouse.y-current_top); 204 return n; 205 } 206 int update_current_group_and_item(HWND hwnd) { 207 int current_group_bak=current_group; 208 int current_item_bak=current_item; 209 int is_group=1; 210 int n=get_current_position(hwnd,is_group); 211 if(n<0)return 0; 212 if(is_group) { 213 current_group=n; 214 current_item=0; 215 current_top=0; 216 } 217 else current_item=n; 218 return (current_group_bak!=current_group)||(current_item_bak!=current_item)?1:0; 219 } 220 void paint_rolan(HWND hwnd,HDC hdc1,HDC hdc) { 221 static HBRUSH bk_brush =CreateSolidBrush (BKCOLOR); 222 static HBRUSH common_item_brush =CreateSolidBrush (COMMON_ITEM_BKCOLOR); 223 static HBRUSH active_item_brush =CreateSolidBrush (ACTIVE_ITEM_BKCOLOR); 224 static HFONT hFont; 225 LOGFONT lf; 226 lf.lfHeight=ITEM_HEIGHT/2.6; 227 lf.lfWidth=0 ; 228 lf.lfEscapement=0 ; 229 lf.lfOrientation=0 ; 230 lf.lfWeight=5; 231 lf.lfItalic=0 ; 232 lf.lfUnderline=0 ; 233 lf.lfStrikeOut=0 ; 234 lf.lfCharSet=DEFAULT_CHARSET ; 235 lf.lfOutPrecision=0 ; 236 lf.lfClipPrecision=0 ; 237 lf.lfQuality=0 ; 238 lf.lfPitchAndFamily=0 ; 239 lstrcpy (lf.lfFaceName, _T("Arial") ); 240 PatBlt(hdc, 0, 0, WIDTH,HEIGHT, WHITENESS); //在绘图前调用这个函数可以把背景重画,WHITENESS可以使背景透明 241 hFont = CreateFontIndirect (&lf) ; 242 SelectFont(hdc,hFont); 243 SelectObject (hdc, GetStockObject (NULL_PEN)) ; 244 SelectObject (hdc,bk_brush); 245 Rectangle(hdc,0,0,WIDTH,HEIGHT); 246 for(int i=0; i<group_num; i++) { 247 if(i==current_group) { 248 SelectObject (hdc,active_item_brush); 249 SetBkColor(hdc,ACTIVE_ITEM_BKCOLOR);//设置文字背景色 250 } else { 251 SelectObject (hdc,common_item_brush); 252 SetBkColor(hdc,COMMON_ITEM_BKCOLOR);//设置文字背景色 253 } 254 Rectangle(hdc,0,i*GROUP_HEIGHT-1,GROUP_WIDTH,(i+1)*GROUP_HEIGHT); 255 TextOut(hdc,GROUP_WIDTH/4,i*GROUP_HEIGHT+GROUP_HEIGHT/4,groups[i].name.c_str(),groups[i].name.length()); 256 } 257 int gitem_num=groups[current_group].item_num; 258 item* items=groups[current_group].items; 259 int item_num=((gitem_num-1)/item_columns+1)*item_columns; 260 int item_count=0; 261 while(item_count<item_num) { 262 int left=GROUP_WIDTH+(item_count%item_columns)*ITEM_WIDTH; 263 int top=current_top+item_count/item_columns*ITEM_HEIGHT; 264 if(item_count==current_item) { 265 SelectObject (hdc,active_item_brush); 266 SetBkColor(hdc,ACTIVE_ITEM_BKCOLOR);//设置文字背景色 267 } else if(item_count<gitem_num){ 268 SelectObject (hdc,common_item_brush); 269 SetBkColor(hdc,COMMON_ITEM_BKCOLOR);//设置文字背景色 270 }else { 271 SelectObject (hdc,bk_brush); 272 } 273 Rectangle(hdc,left-1,top-1,left+ITEM_WIDTH,top+ITEM_HEIGHT); 274 if(item_count<gitem_num)TextOut(hdc,left+ITEM_WIDTH/10,top+ITEM_HEIGHT/4,items[item_count].name.c_str(),items[item_count].name.length()); 275 item_count++; 276 } 277 BitBlt(hdc1, 0, 0, WIDTH, HEIGHT, hdc, 0, 0, SRCCOPY); //将位图直接复制在设备上,关于该函数的使用有很多说明,在这里就不再提了 278 } 279 /* This function is called by the Windows function DispatchMessage() */ 280 281 string get_directory(string path){ 282 int last=path.find_last_of('\\'); 283 return path.substr(0,last); 284 } 285 286 LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 287 { 288 static HDC hdc; 289 static PAINTSTRUCT ps ; 290 static bool is_hide; 291 static int screen_height; 292 static bool not_program_move; 293 static HDC hdcBuffer; 294 switch (message) { /* handle the messages */ 295 case WM_CREATE: { 296 not_program_move=true; 297 is_hide=false; 298 screen_height=GetSystemMetrics(SM_CYSCREEN); 299 load_data(hwnd); 300 current_group=0; 301 current_item=0; 302 InvalidateRect(hwnd,NULL,true); 303 SetTimer(hwnd,0,100,NULL); 304 hdc = GetDC(hwnd); //获取设备 305 hdcBuffer = CreateCompatibleDC(hdc); //给设备分配一个内存空间 306 HBITMAP hBitMap = CreateCompatibleBitmap(hdc, WIDTH, HEIGHT); //创建一个cxClient, cyClient大小并且适应DC设备环境的位图 307 ReleaseDC(hwnd, hdc); 308 SelectObject(hdcBuffer, hBitMap); //将位图设置为hdcBuffer的画刷 309 } 310 break; 311 case WM_MOVE: { 312 RECT rect; 313 GetWindowRect(hwnd,&rect); 314 if(not_program_move&&rect.left<=0&&rect.bottom>=screen_height) { 315 not_program_move=false; 316 MoveWindow(hwnd,1-WIDTH,1-HEIGHT, WIDTH, HEIGHT, FALSE);// screen_height-5 317 not_program_move=true; 318 } 319 is_hide=true; 320 } 321 break; 322 case WM_KEYDOWN: { //识别按键 323 } 324 break; 325 case WM_PAINT: { 326 hdc=BeginPaint (hwnd,&ps) ; 327 paint_rolan(hwnd,hdc,hdcBuffer); 328 EndPaint(hwnd,&ps); 329 } 330 break; 331 case WM_TIMER: { 332 RECT rect; 333 GetClientRect(hwnd,&rect); 334 SetWindowPos(hwnd, HWND_TOPMOST, 1, 1, 1, 1,SWP_NOSIZE|SWP_NOMOVE); 335 } 336 break; 337 case WM_MOUSELEAVE: { 338 not_program_move=true; 339 MoveWindow(hwnd,1-WIDTH,1-HEIGHT, WIDTH, HEIGHT, FALSE);// screen_height-5 340 is_hide=true; 341 } 342 break; 343 case WM_MOUSEHOVER: 344 break; 345 case WM_MOUSEMOVE: { 346 TRACKMOUSEEVENT trmouse; 347 trmouse.cbSize = sizeof(TRACKMOUSEEVENT); 348 trmouse.dwFlags = TME_LEAVE | TME_HOVER;// | TME_NONCLIENT 349 trmouse.dwHoverTime = 2000; 350 trmouse.hwndTrack = hwnd; 351 if(!_TrackMouseEvent(&trmouse)) 352 return FALSE; 353 if(is_hide) { 354 not_program_move=false; 355 MoveWindow(hwnd,0, 0, WIDTH, HEIGHT, FALSE); 356 is_hide=false; 357 } else { 358 if(update_current_group_and_item(hwnd)) 359 InvalidateRect(hwnd,NULL,true); 360 } 361 } 362 break; 363 case WM_MOUSEWHEEL: { //0x020A 364 int flag=0; 365 if( (INT)wParam < 0 ) { 366 int temp=current_top-ITEM_HEIGHT; 367 if(((groups[current_group].item_num-1)/item_columns+1)*ITEM_HEIGHT+temp>0) { 368 current_top=temp; 369 flag=1; 370 } 371 } 372 else { 373 if(current_top<0) {//+ITEM_HEIGHT<get_client_height(hwnd) 374 current_top+=ITEM_HEIGHT; 375 flag=1; 376 } 377 } 378 if(flag) 379 InvalidateRect( hwnd, NULL, TRUE ); 380 } 381 break; 382 case WM_LBUTTONUP: { 383 int t; 384 if(get_current_position(hwnd,t)!=-1&&t==0) { 385 const char* path= groups[current_group].items[current_item].path.c_str(); 386 const char* arguments= groups[current_group].items[current_item].arguments.c_str(); 387 ShellExecute(NULL, "open",path,arguments, get_directory(path).c_str(), SW_SHOWNORMAL); 388 InvalidateRect(hwnd,NULL,true); 389 } 390 } 391 break; 392 case WM_DESTROY: 393 KillTimer(hwnd,0); 394 PostQuitMessage (0); /* send a WM_QUIT to the message queue */ 395 break; 396 default: /* for messages that we don't deal with */ 397 return DefWindowProc (hwnd, message, wParam, lParam); 398 } 399 return 0; 400 }
data.txt的格式如下
2 //组的个数 常用 //组名称 3 //组下项目的个数 Chrome //项目名称 C:\chrome\chrome.exe //程序路径 C:\chrome\chrome.exe //图标路径 www.google.com //运行参数 QQ C:\QQ\bin\QQ.exe C:\QQ\bin\QQ.exe Everything C:\everything\everything.exe C:\everything\everything.exe 网络 1 迅雷 C:\Thunder\thunder.exe C:\Thunder\thunder.exe
2017年4月初写