项目背景:
在自己的电脑装了linux 虚拟机,想要在外网也能ssh到虚拟机进行开发,由于路由ip是动态ip,想到网上找一些动态dns域名解析,但是效果不大好,所以想到自己进行外网ip的管理。
想法:
用C++写一个界面客户端,随系统启动,定时访问自己的cgi,更新自己的外网ip;这个客户端能支持简单的几个操作:启动,退出,设置更新间隔,是否随系统启动等。
写一个cgi,接收client请求,并记录最新的外网ip到数据库;
写另外一个cgi,在其他地方访问能列出当前最新的外网ip,以及历史ip列表。
可以再写一个跳转cgi:jump.php,访问这个cgi能够自动跳转到最新的外网ip对应的目录。
至此,一个简单的动态ip管理和dns解析功能就完成了。
编程环境选择:
Client:C++,MFC;
Server:Php+Mysql,服务器使用sina云平台。
项目进度:
编写CGI,updateip.php?m=update&uid=实现更新外网ip到数据库。
Php中获取ip的方式:
$ip=@$REMOTE_ADDR;
echo "<b>IP Address= $ip</b>";
$ip=$_SERVER['REMOTE_ADDR'];
数据库设计:
Iplist:
建表:
Create table iplist(id int not null auto_increment,
Primary key(id),
uid VARCHAR(32),
ip VARCHAR(32),
updatetime datetime
)
<html>
<body>
CGi代码:
Update.php
<?php
$method = $_GET['m'];
if($method == "update"){
$ip=$_SERVER['REMOTE_ADDR'];
$uid = $_GET['uid'];
echo 'Got it:uid='.$uid.',ip='.$ip.'</BR>';
//mysql_connect($_SAE_MYSQL_HOST_M,$_SAE_MYSQL_USER, $_SAE_MYSQL_PASS) or die(mysql_error());
//mysql_select_db($_SAE_MYSQL_DB) or die(mysql_error());
// Create a MySQL table in the selected database
$mysql = new SaeMysql();
$sql = "INSERT INTO `iplist` (`id`, `uid`, `ip`, `updatetime`) VALUES (NULL, '".$uid."', '".$ip."', now());";
$mysql->runSql( $sql );
if( $mysql->errno() != 0 )
{
die( "Error:" . $mysql->errmsg() );
}
$mysql->closeDb();
}else{
$mysql = new SaeMysql();
$sql = "SELECT *
FROM `iplist`
ORDER BY `updatetime` DESC";
$data = $mysql->getData( $sql );
foreach($data as $i => $value){
echo "Record:id=".$value['id'].",uid=".$value['uid'].",ip".$value['ip'].",updatetime".$value['updatetime']."</BR></BR>";
}
if( $mysql->errno() != 0 )
{
die( "Error:" . $mysql->errmsg() );
}
$mysql->closeDb();
}
?>
</body>
</html>
用MFC编写一个简单的客户端,开机自动启动,定时请求服务器更新外网ip
client端主要代码,基于VS2005,MFC:
UpdateIp.rc
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/
#undef APSTUDIO_READONLY_SYMBOLS
/
// Chinese (P.R.C.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
"#define _AFX_NO_OLE_RESOURCES\r\n"
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
"\r\n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
"LANGUAGE 4, 2\r\n"
"#pragma code_page(936)\r\n"
"#include ""res\\UpdateIp.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
"#include ""afxres.rc"" // Standard components\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON "res\\UpdateIp.ico"
/
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About UpdateIp"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
LTEXT "UpdateIp Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX
LTEXT "Copyright (C) 2012",IDC_STATIC,40,25,119,8
DEFPUSHBUTTON "OK",IDOK,178,7,50,16,WS_GROUP
END
IDD_UPDATEIP_DIALOG DIALOGEX 0, 0, 144, 222
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "UpdateIp"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
PUSHBUTTON "停止服务",IDC_BTN_STOPSERVICE,81,89,50,14
PUSHBUTTON "启动服务",IDC_BTN_STARTSERVICE,17,89,50,14
CONTROL "随系统启动",IDC_CHECK_AUTOSTART,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,25,56,10
EDITTEXT IDC_EDIT_UPDATEINTERVAL,82,46,40,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "更新间隔(秒):",IDC_STATIC,18,49,60,8
GROUPBOX "设置",IDC_STATIC,0,5,135,212
PUSHBUTTON "保存",IDC_SAVE,17,63,50,14
EDITTEXT IDC_EDIT_RESULT,12,119,119,88,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_VSCROLL,WS_EX_STATICEDGE
END
/
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "TODO: <Company name>"
VALUE "FileDescription", "TODO: <File description>"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "UpdateIp.exe"
VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
VALUE "OriginalFilename", "UpdateIp.exe"
VALUE "ProductName", "TODO: <Product name>"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
/
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 228
TOPMARGIN, 7
BOTTOMMARGIN, 48
END
IDD_UPDATEIP_DIALOG, DIALOG
BEGIN
RIGHTMARGIN, 142
END
END
#endif // APSTUDIO_INVOKED
/
//
// String Table
//
STRINGTABLE
BEGIN
IDS_ABOUTBOX "&About UpdateIp…"
IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed."
END
#endif // Chinese (P.R.C.) resources
/
#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE 4, 2
#pragma code_page(936)
#include "res\UpdateIp.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#endif
/
#endif // not APSTUDIO_INVOKED
UpdateIpDlg.h
// UpdateIpDlg.h : header file
//
#pragma once
// CUpdateIpDlg dialog
class CUpdateIpDlg : public CDialog
{
// Construction
public:
CUpdateIpDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_UPDATEIP_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedBtnStartservice();
afx_msg void OnBnClickedBtnStopservice();
afx_msg void OnTimer(UINT_PTR nIDEvent );
afx_msg void OnDestroy();
BOOL OnEraseBkgnd(CDC* pDC);
int OnCreate(LPCREATESTRUCT lpCreateStruct);
LRESULT OnNotifyIcon(WPARAM wParam,LPARAM IParam);
private:
void startService(int interval);
void stopService();
void startUpdateInstance();
void stopUpdateInstance();
BOOL setAutoStart(BOOL bVal);
void initSettings();
BOOL saveSettings();
CString getSettingFilePath();
void addNotification();
public:
afx_msg void OnBnClickedSave();
private:
int m_nTimer;
BOOL m_bAutoStart;
int m_nUpdateInterval;
int m_bIsRunning;
CString m_strSettingFilepath;
NOTIFYICONDATA NotifyIcon;
};
UpdateIpDlg.cpp
// UpdateIpDlg.cpp : implementation file
//
#include "stdafx.h"
#include "UpdateIp.h"
#include "UpdateIpDlg.h"
#include "lib/happyhttp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define WM_NC (WM_USER+1001)
const int TIMER_UPDATE = 100;
const TCHAR c_szSettingFilename[] = _T("updateip.ini");
const int c_nDefaultUpdate = 300;
const char c_szRequestHost[] = "xx.sinaapp.com"; //换成自己的域名
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CUpdateIpDlg dialog
CUpdateIpDlg::CUpdateIpDlg(CWnd* pParent /*=NULL*/)
: CDialog(CUpdateIpDlg::IDD, pParent)
, m_nTimer(0)
, m_bAutoStart(TRUE)
, m_nUpdateInterval(c_nDefaultUpdate)
, m_bIsRunning(FALSE)
, m_strSettingFilepath(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CUpdateIpDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CUpdateIpDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
ON_WM_DESTROY()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BTN_STARTSERVICE, &CUpdateIpDlg::OnBnClickedBtnStartservice)
ON_BN_CLICKED(IDC_BTN_STOPSERVICE, &CUpdateIpDlg::OnBnClickedBtnStopservice)
ON_BN_CLICKED(IDC_SAVE, &CUpdateIpDlg::OnBnClickedSave)
ON_MESSAGE(WM_NC,OnNotifyIcon)
END_MESSAGE_MAP()
// CUpdateIpDlg message handlers
BOOL CUpdateIpDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About…" menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
initSettings();
GetDlgItem(IDC_BTN_STARTSERVICE)->EnableWindow(FALSE);
GetDlgItem(IDC_BTN_STOPSERVICE)->EnableWindow(TRUE);
m_bIsRunning = TRUE;
startService(m_nUpdateInterval);
startUpdateInstance();
return TRUE; // return TRUE unless you set the focus to a control
}
void CUpdateIpDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}else if ((nID & 0xFFF0) == SC_MINIMIZE )
{
ShowWindow(SW_HIDE);
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CUpdateIpDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() – cxIcon + 1) / 2;
int y = (rect.Height() – cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CUpdateIpDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CUpdateIpDlg::OnBnClickedBtnStartservice()
{
// TODO: Add your control notification handler code here
GetDlgItem(IDC_BTN_STARTSERVICE)->EnableWindow(FALSE);
GetDlgItem(IDC_BTN_STOPSERVICE)->EnableWindow(TRUE);
startService(m_nUpdateInterval);
}
void CUpdateIpDlg::OnBnClickedBtnStopservice()
{
// TODO: Add your control notification handler code here
GetDlgItem(IDC_BTN_STARTSERVICE)->EnableWindow(TRUE);
GetDlgItem(IDC_BTN_STOPSERVICE)->EnableWindow(FALSE);
stopService();
}
void CUpdateIpDlg::OnTimer(UINT_PTR nIDEvent ){
startUpdateInstance();
}
void CUpdateIpDlg::OnDestroy(){
Shell_NotifyIcon(NIM_DELETE, &NotifyIcon);
return CDialog::OnDestroy();
}
BOOL CUpdateIpDlg::OnEraseBkgnd(CDC* pDC){
static bool bFirst=true;
if(bFirst)
{
bFirst=false;
ShowWindow(SW_HIDE);
return TRUE;
}
return CDialog::OnEraseBkgnd(pDC);
}
int CUpdateIpDlg::OnCreate(LPCREATESTRUCT lpCreateStruct){
addNotification();
return CDialog::OnCreate(lpCreateStruct);
}
void CUpdateIpDlg::startService(int interval){
m_nTimer = SetTimer(TIMER_UPDATE,interval * 1000,0);
m_bIsRunning = TRUE;
CString strResult;
GetDlgItemText(IDC_EDIT_RESULT,strResult);
strResult += _T("startService:\r\n");
SetDlgItemText(IDC_EDIT_RESULT,strResult);
}
void CUpdateIpDlg::stopService(){
KillTimer(m_nTimer);
stopUpdateInstance();
m_bIsRunning = FALSE;
CString strResult;
GetDlgItemText(IDC_EDIT_RESULT,strResult);
strResult += _T("stopService:\r\n");
SetDlgItemText(IDC_EDIT_RESULT,strResult);
}
int count=0;
void OnBegin( const happyhttp::Response* r, void* userdata )
{
printf( "BEGIN (%d %s)\n", r->getstatus(), r->getreason() );
count = 0;
}
void OnData( const happyhttp::Response* r, void* userdata, const unsigned char* data, int n )
{
fwrite( data,1,n, stdout );
count += n;
}
void OnComplete( const happyhttp::Response* r, void* userdata )
{
printf( "COMPLETE (%d bytes)\n", count );
}
void CUpdateIpDlg::startUpdateInstance(){
//启动新的线程去发起Http请求
stopUpdateInstance();
CString strResult;
GetDlgItemText(IDC_EDIT_RESULT,strResult);
strResult += _T("启动更新请求:\r\n");
SetDlgItemText(IDC_EDIT_RESULT,strResult);
try
{
char uid[] = "0000";
char szTemp[1024] = {0};
_snprintf_s(szTemp,sizeof(szTemp),sizeof(szTemp),"/updateip.php?m=update&uid=%s",uid);
happyhttp::Connection conn(c_szRequestHost, 80 );
conn.setcallbacks( OnBegin, OnData, OnComplete, 0 );
conn.request( "GET", szTemp, 0, 0,0 );
while( conn.outstanding() )
conn.pump();
/*
TCHAR uid[] = _T("0000");
TCHAR szTemp[1024] = {0};
_sntprintf_s(szTemp,sizeof(szTemp),sizeof(szTemp),_T("/updateip.php?m=update&uid=%s"),uid);
BOOL bResults = FALSE;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen( L"A WinHTTP Example Program/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect( hSession, c_szRequestHost,
INTERNET_DEFAULT_HTTP_PORT, 0);
// Create an HTTP Request handle.
if (hConnect)
hRequest = WinHttpOpenRequest( hConnect, L"PUT", szTemp,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
// Send a Request.
if (hRequest)
bResults = WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0,
0, 0);
// Place additional code here.
// Report errors.
if (!bResults{
CString strResult;
GetDlgItemText(IDC_EDIT_RESULT,strResult);
strResult += _T("请求发送失败,URL = ");
strResult += c_szRequestHost;
strResult += szTemp;
strResult += "\r\n";
SetDlgItemText(IDC_EDIT_RESULT,strResult);
}else{
CString strResult;
GetDlgItemText(IDC_EDIT_RESULT,strResult);
strResult += _T("请求发送成功,URL = ");
strResult += c_szRequestHost;
strResult += szTemp;
strResult += "\r\n";
SetDlgItemText(IDC_EDIT_RESULT,strResult);
}
printf("Error %d has occurred.\n",GetLastError());
// Close open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);*/
}catch( happyhttp::Wobbly& e )
{
printf("Exception:\n%s\n", e.what() );
}
}
void CUpdateIpDlg::stopUpdateInstance(){
CString strResult;
GetDlgItemText(IDC_EDIT_RESULT,strResult);
strResult += _T("停止更新请求:\r\n");
SetDlgItemText(IDC_EDIT_RESULT,strResult);
}
BOOL CUpdateIpDlg::setAutoStart(BOOL bVal){
HKEY hKey;
long return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",0,KEY_READ| KEY_WRITE,&hKey );
if (ERROR_SUCCESS == return_val)
{
if (bVal)
{
TCHAR pathtofile[MAX_PATH] = {0};
GetModuleFileName(NULL,pathtofile,MAX_PATH);
if (ERROR_SUCCESS != RegSetValueEx(hKey,_T("autoupdateip"),0,REG_SZ,(byte *)pathtofile,sizeof(pathtofile)))
{
RegCloseKey(hKey);
return FALSE;
}
}else{
long ret = RegDeleteValue(hKey,_T("autoupdateip"));
if (ERROR_SUCCESS != ret && ret != ERROR_FILE_NOT_FOUND)
{
int err = GetLastError();
RegCloseKey(hKey);
return FALSE;
}
}
RegCloseKey(hKey);
return TRUE;
}
return FALSE;
}
void CUpdateIpDlg::OnBnClickedSave()
{
// TODO: Add your control notification handler code here
m_bAutoStart = ((CButton *)GetDlgItem(IDC_CHECK_AUTOSTART))->GetCheck();
if (!setAutoStart(m_bAutoStart))
{
MessageBox(_T("setAutoStart error!"));
}
m_nUpdateInterval = GetDlgItemInt(IDC_EDIT_UPDATEINTERVAL);
if (m_bIsRunning)
{
stopService();
startService(m_nUpdateInterval);
}
if(!saveSettings()){
MessageBox(_T("saveSettings error!"));
}else{
MessageBox(_T("saveSettings Success!"));
}
}
void CUpdateIpDlg::initSettings(){
m_strSettingFilepath = getSettingFilePath();
m_bAutoStart = (BOOL)GetPrivateProfileInt(_T("config"),_T("autostart"),1,m_strSettingFilepath);
m_nUpdateInterval = GetPrivateProfileInt(_T("config"),_T("updateinterval"),c_nDefaultUpdate,m_strSettingFilepath);
((CButton *)GetDlgItem(IDC_CHECK_AUTOSTART))->SetCheck(m_bAutoStart);
if (!setAutoStart(m_bAutoStart))
{
MessageBox(_T("setAutoStarterror"));
}
SetDlgItemInt(IDC_EDIT_UPDATEINTERVAL,m_nUpdateInterval);
}
BOOL CUpdateIpDlg::saveSettings(){
CString strTemp;
strTemp.Format(_T("%d"),m_bAutoStart);
if (!WritePrivateProfileString(_T("config"),_T("autostart"),strTemp,m_strSettingFilepath))
{
return FALSE;
}
strTemp.Format(_T("%d"), m_nUpdateInterval);
if (!WritePrivateProfileString(_T("config"),_T("updateinterval"),strTemp,m_strSettingFilepath))
{
return FALSE;
}
return TRUE;
}
CString CUpdateIpDlg::getSettingFilePath(){
TCHAR szPath[MAX_PATH] = {0};
BOOL bRet = SHGetSpecialFolderPath(NULL,szPath,CSIDL_APPDATA,FALSE);
if (!bRet)
{
MessageBox(_T("SHGetSpecialFolderPath Failed!"));
return _T("");
}
CString strFolder = szPath;
strFolder += "\\autoupdateip\\";
if (!CreateDirectory(strFolder,NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
{
MessageBox(_T("创建临时目录失败!"));
return _T("");
}
return strFolder + c_szSettingFilename;
}
LRESULT CUpdateIpDlg::OnNotifyIcon(WPARAM wParam,LPARAM IParam)
{
if ((IParam == WM_LBUTTONDOWN) || (IParam == WM_RBUTTONDOWN))
{
ModifyStyleEx(0,WS_EX_TOPMOST);
ShowWindow(SW_RESTORE);
//Shell_NotifyIcon(NIM_DELETE, &NotifyIcon);
}
return 0;
}
void CUpdateIpDlg::addNotification(){
NotifyIcon.cbSize=sizeof(NOTIFYICONDATA);
NotifyIcon.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
NotifyIcon.hWnd=m_hWnd;
lstrcpy(NotifyIcon.szTip,_T("Auto Update IP by weibin"));
NotifyIcon.uCallbackMessage=WM_NC;
NotifyIcon.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;
Shell_NotifyIcon(NIM_ADD,&NotifyIcon);
}
原文链接:https://blog.csdn.net/weixin_34148340/article/details/94645663