1. 程式人生 > >專案實戰篇-餐館管理系統—MFC,PHP,MySql:2.登陸功能的實現

專案實戰篇-餐館管理系統—MFC,PHP,MySql:2.登陸功能的實現

1.mysql 資料庫的建立
首先在虛擬機器終端上利用 ifconfig 獲取虛擬機器IP。
獲取IP
然後在本地計算機瀏覽器位址列輸入 http://192.168.200.128/phpmyadmin 如果載入不成功檢查Ubuntu是否安裝phpmyadmin。
這裡寫圖片描述
輸入mysql的賬號和密碼進入。並且新建一個名為 sdb 的資料庫
這裡寫圖片描述
及其對應的表:
privilege
這裡寫圖片描述
users
這裡寫圖片描述
2.後端PHP程式碼
db_info.php

<?php
/**
 * Created by PhpStorm.
 * User: pldq
 * Date: 16-12-13
 * Time: 下午8:31
 */
#echo "From db_info.php"; # databases infomation static $DB_HOST="localhost"; static $DB_NAME="sdb"; static $DB_USER="root"; static $DB_PASS="******"; global $con; $con = mysqli_connect($DB_HOST, $DB_USER, $DB_PASS); if ($con == null) { die("FAILED|Could not connect:" . mysqli_error() . "<br>"
); } if (!mysqli_select_db($con, "sdb")) { die("FAILED|Could't use foo: " . mysqli_error()); } ?>

login.php

<?php
   session_start();
   require_once ('db_info.php');
//    echo "Hello World!";
//    echo $_REQUEST["username"];
//    echo $_REQUEST["psd"];
    $username = $_POST["username"
]; $psd = $_POST["psd"]; // $phone = $_POST["phone"]; // $email = $_POST["email"]; $sql_username = "Select * from users WHERE username = '" . $username . "'"; $mysqli_result = mysqli_query($con, $sql_username); $row = mysqli_fetch_array($mysqli_result); if (mysqli_num_rows($mysqli_result) == 0) { die("FAILED|The username is not existed!"); } if ($row['password'] === $psd and strlen($psd) > 6) { $str_ret = "SUCCEED|SUCCEED LOGIN IN THE SYSTEM!|"; $sql_get_privilege = "Select * from privilege WHERE username = '" . $username . "'"; $mysqli_privilege_result = mysqli_query($con, $sql_get_privilege); if (mysqli_num_rows($mysqli_result) == 0) { $_SESSION['user'] = $username; die($str_ret); } else { $row = mysqli_fetch_array($mysqli_privilege_result); $_SESSION['user'] = $username; $_SESSION['rightstr'] = $row['rightstr']; die($str_ret . $row['rightstr']); } } else { die("FAILED|The password is incorrect!"); } mysqli_close($con); // close db connect ?>

然後將程式碼上傳到Ubuntu 站點目錄下
這裡寫圖片描述
這樣網頁後端就編寫成功了!
3.MFC 端
1、利用 MFC 生成嚮導生成一個基於對話方塊的程式。
這裡寫圖片描述

使用GDI繪圖:

#include <gdiplus.h>

#pragma comment(lib, "gdiplus.lib")

using namespace Gdiplus;

// Bitmap* m_mainImage; // 宣告為類成員

BOOL CManagementSystemDlg::OnInitDialog()
{
    // 初始化 GDI+
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
    // !其餘程式碼沒有進行修改、刪除
}

void CManagementSystemDlg::OnClose()
{
    // 釋放GDI+
    GdiplusShutdown(m_gdiplusToken);
}

繪製圖片:


#define IMAGE_MAIN_FILENAME L"Important\\res_login\\main.jpg"

BOOL CManagementSystemDlg::OnInitDialog()
{
    // 載入圖片到記憶體
    m_mainImage = Bitmap::FromFile(IMAGE_MAIN_FILENAME);
}

void CManagementSystemDlg::OnPaint()
{
    CClientDC Clientdc(this);

    Graphics graphics(Clientdc.GetSafeHdc());

    // 繪製圖片
    graphics.DrawImage(m_mainImage, 0, 0, m_mainImage->GetWidth(), m_mainImage->GetHeight());
}

然後編譯執行、、、
這裡寫圖片描述
但是執行後發現視窗並不能實現拖動。為了實現視窗拖動我們還需要讓對話方塊響應 WM_NCHITTEST 訊息。讓它把點選再視窗客戶區的訊息響應為在標題欄點選的訊息。

LRESULT CManagementSystemDlg::OnNcHitTest(CPoint point)
{
    // TODO:  在此新增訊息處理程式程式碼和/或呼叫預設值
    CRect rc;
    GetClientRect(&rc);
    ClientToScreen(&rc);
    int x = point.x;
    int y = point.y;
    if (x >= rc.left && x <= rc.right && y >= rc.top && y <= rc.bottom)
    {
        return HTCAPTION;
    }
    else {
        return CDialogEx::OnNcHitTest(point);
    }
}

退出按鈕的事件程式碼:

void CManagementSystemDlg::OnBnClickedButtonExit()
{
    // TODO:  在此新增控制元件通知處理程式程式碼
    this->SendMessage(WM_CLOSE, 0, 0);
}

登陸按鈕的事件程式碼:

HTTP訪問:
1. 利用MFC 裡面的CSession、CHttpConnection等函式:(實現失敗!)


#include <afxinet.h>

void Ansi2Wchar(std::string strSource, CString& strDest)
{
    int length = 0;
    length = ::MultiByteToWideChar(CP_ACP, 0, strSource.c_str(), strSource.length(), 0, 0);
    WCHAR* Buffer = new WCHAR[length + 1];
    memset(Buffer, 0, (length + 1) * sizeof(WCHAR));
    ::MultiByteToWideChar(CP_ACP, 0, strSource.c_str(), strSource.length(), Buffer, length);
    strDest = Buffer;
    delete[] Buffer;
}

void Wchar2Ansi(CString strSource, std::string& strDest)
{
    int length = 0;
    length = ::WideCharToMultiByte(CP_ACP, 0, strSource.GetBuffer(), strSource.GetLength(), 0, 0, 0, 0);
    strSource.ReleaseBuffer();
    CHAR* Buffer = new CHAR[length + 1];
    memset(Buffer, 0, sizeof(CHAR)* (length + 1));
    ::WideCharToMultiByte(CP_ACP, 0, strSource.GetBuffer(), strSource.GetLength(), Buffer, length, 0, 0);
    strSource.ReleaseBuffer();
    strDest = Buffer;
    delete[] Buffer;
}

void CManagementSystemDlg::OnBnClickedButtonLogin()
{
    // TODO:  在此新增控制元件通知處理程式程式碼
    UpdateData(TRUE);
    CString strUrl = L"http://192.168.200.128/myAdminSystem/login.php";
    DWORD dwServiceType = AFX_INET_SERVICE_HTTP;
    CString strServer = L"";
    CString strObject = L"";
    INTERNET_PORT nPort = 80;

    if (!AfxParseURL(strUrl, dwServiceType, strServer, strObject, nPort))
    {
        return;
    }
    CInternetSession mysession(L"session", 0);
    mysession.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 1000 * 20);
    mysession.SetOption(INTERNET_OPTION_CONNECT_BACKOFF, 1000);
    mysession.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1);
    CHttpConnection* mycon = mysession.GetHttpConnection(strServer, INTERNET_FLAG_KEEP_CONNECTION, nPort);
    CHttpFile* myfile = mycon->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject, 0, 1, 0, L"HTTP/1.1", INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE);
    CString strPostData = L"username=" + strUSER + L"&psd=" + strPsd;
    std::string strPost = "";
    Wchar2Ansi(strPostData, strPost);
    CString strHeaders = L"Content-Type: application/x-www-form-urlencoded\r\nAccept: */*\r\n";
    BOOL result = myfile->SendRequest(strHeaders, (LPVOID)strPost.c_str(), strPost.size());
    strHeaders.ReleaseBuffer();
    strPostData.ReleaseBuffer();

    CHAR Buffer[1024 + 1] = { 0 };
    memset(Buffer, 0, (1024 + 1) * sizeof(CHAR));
    std::string strRawResponse = "";
    UINT nReaded = 0;
    while ((nReaded = myfile->Read((void*)Buffer, 1024)) > 0)
    {
        Buffer[nReaded] = '\0';
        strRawResponse += Buffer;
        memset(Buffer, 0, (1024 + 1) * sizeof(CHAR));
    }
    CString strResponse = L"";
    Ansi2Wchar(strRawResponse, strResponse);

    if (strResponse.GetLength() <= 0)
    {
        MessageBox(L"獲取資料失敗!", L"Info", MB_OK | MB_ICONWARNING);
        return;
    }
}

這個 Bug 很奇怪,當我開啟 Fiddler 進行抓包時 SendRequest 可以成功使用,當我關閉 Fiddler 的抓包功能時它會彈出 “無法與伺服器建立連線的資訊框”
這裡寫圖片描述
2. 利用WinHttp 的 com 元件智慧指標程式設計(實現簡單、現使用)

#import "C:\\windows\\system32\\winhttp.dll"

#define STRING_LOGIN_HOST_ADDRESS L"http://192.168.200.128/myAdminSystem/login.php"

void CManagementSystemDlg::OnBnClickedButtonLogin()
{
    // TODO:  在此新增控制元件通知處理程式程式碼
    UpdateData(TRUE);
    CString strPostData = L"username=" + strUSER + L"&psd=" + strPsd;
    // using com programming winhttp
    WinHttp::IWinHttpRequestPtr ptrHttp = nullptr;
    ptrHttp.CreateInstance(__uuidof(WinHttp::WinHttpRequest));
    if (0 != ptrHttp->Open(L"POST", STRING_LOGIN_HOST_ADDRESS))
    {
        MessageBox(L"伺服器連線失敗!", L"Info", MB_OK | MB_ICONSTOP);
        return;
    }
    ptrHttp->SetRequestHeader(L"User-Agent", L" Mozilla / 5.0 (Windows NT 6.1; WOW64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 50.0.2661.102 Safari / 537.36");
    ptrHttp->SetRequestHeader(L"Content-Type", L"application/x-www-form-urlencoded");
    ptrHttp->Send(strPostData.GetBuffer());
    strPostData.ReleaseBuffer();
    CString strResult = ptrHttp->GetResponseText();
    CString strCookie = ptrHttp->GetResponseHeader(L"Set-Cookie"); // get http post cookie
    strCookie.Replace(L"; path=/", L"");
}

對HTTP返回訊息的處理:

    if (strResult.GetLength() <= 0)
    {
        MessageBox(L"獲取資料失敗!", L"Info", MB_OK | MB_ICONWARNING);
        return;
    }

    if (-1 == strResult.Find(L"FAILED"))
    {
        int index = 0;
        CString strCaption = strResult.Mid(index, strResult.Find(L"|", index) - index);
        index = strResult.Find(L"|", index) + 1;
        CString strInformation = strResult.Mid(index, strResult.Find(L"|", index) - index);
        index = strResult.Find(L"|", index) + 1;
        CString session = strResult.Mid(index, strResult.GetLength() - index);
        MessageBox(strInformation, strCaption, MB_OK | MB_ICONINFORMATION);

        // TODO
    } else {
        int index = 0;
        CString strCaption = strResult.Mid(index, strResult.Find(L"|", index) - index);
        index = strResult.Find(L"|", index) + 1;
        CString strInformation = strResult.Mid(index, strResult.GetLength() - index);
        MessageBox(strInformation, strCaption, MB_OK | MB_ICONSTOP);
        return;
    }

這樣一個登陸功能就成功實現了!
這裡寫圖片描述
這裡寫圖片描述