滑动密码锁程序

类似于手机的滑屏解锁功能,只实现了简单的功能,现在还没有实现锁图大小的自适应适应功能和自己随意设置密码功能,需要在程序代码里先设置密码。

为了程序规范,创建一个 lock 文件夹,里面并包含 code、execute、image 三个文件夹。

1、在code里创建源代码文件:

   main.c

#include "gtk_window.h"
WINDOW window;//定义结构体变量
int main (int argc, char *argv[])
{
	gtk_init (&argc, &argv);
	window_demo(&window);	// 窗口的相关操作
	gtk_main();
	return 0;
}

   gtk_window.c

#include "gtk_function.h"
#include "gtk_window.h"
int lock_image_place[9][4]={{250,325,90,165},
							{360,435,90,165},
							{470,545,90,165},
							{250,325,200,275},
							{360,435,200,275},
							{470,545,200,275},
							{250,325,310,385},
							{360,435,310,385},
							{470,545,310,385}};
int xy[9][2]={{288,128},
			  {398,128},
			  {508,128},
			  {288,238},
			  {398,238},
			  {508,238},
			  {288,348},
			  {398,348},
			  {508,348}};
int flag[]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
int password[]={1,4,7,8,-2};
int count;
guint timer;

/*******************************************************************
* 函数功能:窗口控件的创建、设置、布局、信号连接
* 参数类型:data:WINDOW变量的地址
* 返回类型:无
********************************************************************/
void window_demo(gpointer data)
{
	WINDOW *p_temp = (WINDOW *)data;	
	p_temp->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);	// 创建主窗口
	gtk_window_set_title(GTK_WINDOW(p_temp->main_window), "window");	 	// 设置窗口标题
	gtk_window_set_position(GTK_WINDOW(p_temp->main_window), GTK_WIN_POS_CENTER); // 设置窗口在显示器中的位置为居中
	gtk_widget_set_size_request(p_temp->main_window, 800, 480);	  // 设置窗口的最小大小
	gtk_window_set_resizable(GTK_WINDOW(p_temp->main_window), FALSE); // 固定窗口的大小
	gtk_container_set_border_width(GTK_CONTAINER(p_temp->main_window), 1);	// 窗口边距
	chang_background(p_temp->main_window, 800, 480, "../image/background.jpg");// 设置主窗口背景图
	gtk_widget_set_app_paintable(p_temp->main_window, TRUE);	// 允许窗口可以绘图
	
	p_temp->main_table = gtk_table_new(48, 80, TRUE);// 创建表格布局容器
	gtk_container_add(GTK_CONTAINER(p_temp->main_window), p_temp->main_table);//把表格布局放入窗口
	int i=0;
	for(i=0;i<9;i++)
	{
		p_temp->lock_image[i]=image_new_from_file("../image/main.png",80,80);//创建锁点的图片
		gtk_table_attach_defaults(GTK_TABLE(p_temp->main_table), p_temp->lock_image[i], 25+((i%3)*11), 33+((i%3)*11), 9+(i/3)*11, 17+(i/3)*11);//把锁点放入表格布局
	}
	
	gtk_widget_add_events(p_temp->main_window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK);// 窗口接收鼠标点击、移动、释放事件
	g_signal_connect(p_temp->main_window, "motion-notify-event", G_CALLBACK(mouse_callback), p_temp);//接收鼠标滑动时间
	g_signal_connect(p_temp->main_window, "button-release-event", G_CALLBACK(lock_callback), p_temp);//接收鼠标滑动时间
	
	g_signal_connect(p_temp->main_window, "expose-event", G_CALLBACK(on_expose_event), p_temp);//曝光事件用于画线
	gtk_widget_show_all(p_temp->main_window);//显示控件
}
/*******************************************************************
* 函数功能:鼠标处理回调函数
* 参数类型:widget:控件变量
		   event:鼠标信号
		   data:WINDOW变量的地址  
* 返回类型:无
********************************************************************/
gboolean mouse_callback(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	WINDOW *p_temp = (WINDOW *)data;
	int i=0;
	p_temp->x=(int)event->x;
	p_temp->y=(int)event->y;	
	for(i=0;i<9;i++)
	{
		if((p_temp->x>lock_image_place[i][0]&&p_temp->x<lock_image_place[i][1])&&(p_temp->y>lock_image_place[i][2]&&p_temp->y<lock_image_place[i][3]))//判断与锁点的坐标匹配
		{
			if(count==0)
			{
				load_image(p_temp->lock_image[i],"../image/right.png",80,80);
				flag[0]=i;
				count++;
			}
			else if(i!=flag[count-1]&&count<TOTAL_DOT)
			{
				load_image(p_temp->lock_image[i],"../image/right.png",80,80);
				flag[count]=i;
				count++;
			}
		}
	}
	return TRUE;
}
/*******************************************************************
* 函数功能:锁控制回调函数
* 参数类型:widget:控件变量
		   event:鼠标信号
		   data:WINDOW变量的地址  
* 返回类型:无
********************************************************************/
gboolean lock_callback(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	WINDOW *p_temp = (WINDOW *)data;
	int i=0;
	while(flag[i]==password[i])//密码与输入匹配判断
		i++;
	if(password[i]==-2&&flag[i]<0)
	{
		for(i=0;i<count;i++)
		{
			load_image(p_temp->lock_image[flag[i]],"../image/main.png",80,80);
			flag[i]=-1;//flag数组赋成-1,以备下次用
		}
		printf("****hello*****\n");
		count=0;//赋成0,以备下次用
	}
	else
	{
		for(i=0;i<count;i++)
			load_image(p_temp->lock_image[flag[i]],"../image/error.png",80,80);
		timer=g_timeout_add(1500,(GSourceFunc)deal_time,data);
	}
	return TRUE;
}
/*******************************************************************
* 函数功能:曝光事件用于画线
* 参数类型:widget:控件变量
		   event:鼠标信号
		   data:WINDOW变量的地址  
* 返回类型:无
********************************************************************/
gboolean on_expose_event(GtkWidget * widget, GdkEventExpose *event, gpointer data)
{
	WINDOW *p_temp = (WINDOW *)data;
	int i=0;
	cairo_t *cr = gdk_cairo_create(widget->window);	// 创建cairo环境
	cairo_set_line_width(cr, 25);	// 线宽设置
	cairo_set_source_rgb(cr, 0, 1, 0);	// 设置环境的前景色,暗红色
	if(flag[0]>0&&flag[1]<0)
	{
		cairo_move_to(cr, xy[flag[0]][0], xy[flag[0]][1]);		// 起点
		cairo_line_to(cr, p_temp->x, p_temp->y);		// 终点
		cairo_stroke(cr);				// 绘制cairo环境的路径
	}
	else if(flag[1]>-1)
	{
		for(i=0;i<count-1;i++)
		{
			cairo_move_to(cr, xy[flag[i]][0], xy[flag[i]][1]);		// 起点
			cairo_line_to(cr, xy[flag[i+1]][0], xy[flag[i+1]][1]);	// 终点
			cairo_stroke(cr);				// 绘制cairo环境的路径
		}
	}
	gtk_widget_queue_draw(p_temp->main_window);	// 更新刷图区域
	cairo_destroy(cr);	// 回收所有Cairo环境所占用的内存资源
	return FALSE;
}
/*******************************************************************
* 函数功能:定时器回调函数,用于把锁图恢复到开始状态
* 参数类型: data:WINDOW变量的地址  
* 返回类型:TRUE:定时器继续工作,FALSE:定时器停止工作
********************************************************************/
gboolean deal_time(gpointer data)
{
	WINDOW *p_temp = (WINDOW *)data;
	int i=0;
	for(i=0;i<count;i++)
	{
		load_image(p_temp->lock_image[flag[i]],"../image/main.png",80,80);
		flag[i]=-1;//flag数组赋成-1,以备下次用
	}
	count=0;//赋成0,以备下次用
	g_source_remove(timer);
	return TRUE;
}

   gtk_window.h

#ifndef _GTK_WINDOW_H_
#define _GTK_WINDOW_H_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <cairo.h>	// 绘图所需要的头文件

#define TOTAL_DOT 20
typedef struct _window
{
	GtkWidget *main_window;//主窗口
	GtkWidget *main_table;//表格布局
	GtkWidget *lock_image[9];//锁的图片
	int x;//获取到的触摸坐标
	int y;

}WINDOW; 

 /*******************************************************************
* 函数功能:窗口控件的创建、设置、布局、信号连接
* 参数类型:data:WINDOW变量的地址
* 返回类型:无
********************************************************************/
void window_demo(gpointer data);
/*******************************************************************
* 函数功能:鼠标处理回调函数
* 参数类型:widget:控件变量
		   event:鼠标信号
		   data:WINDOW变量的地址  
* 返回类型:无
********************************************************************/
gboolean mouse_callback(GtkWidget *widget, GdkEventButton *event, gpointer data);
/*******************************************************************
* 函数功能:锁控制回调函数
* 参数类型:widget:控件变量
		   event:鼠标信号
		   data:WINDOW变量的地址  
* 返回类型:无
********************************************************************/
gboolean lock_callback(GtkWidget *widget, GdkEventButton *event, gpointer data);
/*******************************************************************
* 函数功能:曝光事件用于画线
* 参数类型:widget:控件变量
		   event:鼠标信号
		   data:WINDOW变量的地址  
* 返回类型:无
********************************************************************/
gboolean on_expose_event (GtkWidget * widget, GdkEventExpose * event, gpointer data);
/*******************************************************************
* 函数功能:定时器回调函数,用于把锁图恢复到开始状态
* 参数类型: data:WINDOW变量的地址  
* 返回类型:TRUE:定时器继续工作,FALSE:定时器停止工作
********************************************************************/
gboolean deal_time(gpointer data);

#endif

 

   gtk_function.c

#include "gtk_function.h"
/*******************************************************************
* 函数功能:设置背景图
* 参数类型:widget: 主窗口
           w, h:   图片的大小
           path:  图片路径
* 返回类型:无
********************************************************************/
void chang_background(GtkWidget *widget, int w, int h, const gchar *path)
{
	gtk_widget_set_app_paintable(widget, TRUE);		//允许窗口可以绘图
    gtk_widget_realize(widget);	
	
	/* 更改背景图时,图片会重叠
	 * 这时要手动调用下面的函数,让窗口绘图区域失效,产生窗口重绘制事件(即 expose 事件)。
	 */
	gtk_widget_queue_draw(widget);
	
    GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file(path, NULL);	// 创建图片资源对象
    // w, h是指定图片的宽度和高度
    GdkPixbuf *dst_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR);

	GdkPixmap *pixmap = NULL;
	
	/* 创建pixmap图像; 
	 * NULL:不需要蒙版; 
	 * 123: 0~255,透明到不透明
	 */
    gdk_pixbuf_render_pixmap_and_mask(dst_pixbuf, &pixmap, NULL, 128);
    // 通过pixmap给widget设置一张背景图,最后一个参数必须为: FASLE
	gdk_window_set_back_pixmap(widget->window, pixmap, FALSE);
    
	// 释放资源
	g_object_unref(src_pixbuf);
    g_object_unref(dst_pixbuf);
    g_object_unref(pixmap);
}

 /*******************************************************************
* 函数功能:创建一张图片
* 参数类型:image_path:图片路径
           w, h:   图片的大小 
* 返回类型:图片控件
********************************************************************/
GtkWidget *image_new_from_file(const char *image_path, int w, int h)
{
	GtkWidget *image = NULL;
	GdkPixbuf *src_pixbuf = NULL;
    GdkPixbuf *dst_pixbuf = NULL;
	
    src_pixbuf = gdk_pixbuf_new_from_file(image_path, NULL);//创建图片资源对象
    dst_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR);//设置图片大小
	image = gtk_image_new_from_pixbuf(dst_pixbuf);//通过图片资源对象创建图片控件
    g_object_unref(dst_pixbuf);//释放图片资源
	
	if(NULL == image)
	{
		return NULL;
	}
	else
	{
		return image;
	}
}
/*******************************************************************
* 函数功能:给创建好的image重新设计一张图片
* 参数类型:image:    图片控件
           w, h:   图片的大小
           file_path:  图片路径
* 返回类型:无
********************************************************************/
void load_image(GtkWidget *image, const char *file_path, const int w, const int h )
{
	gtk_image_clear( GTK_IMAGE(image) );  // 清除图像
	GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file(file_path, NULL);	// 创建图片资源
	GdkPixbuf *dest_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR); // 指定大小
	gtk_image_set_from_pixbuf(GTK_IMAGE(image), dest_pixbuf); // 图片控件重新设置一张图片(pixbuf)
	g_object_unref(src_pixbuf);		// 释放资源
	g_object_unref(dest_pixbuf);	// 释放资源
}

   gtk_function.h

#ifndef _GTK_FUNCTION_H_
#define _GTK_FUNCTION_H_
#include <gtk/gtk.h>
/*******************************************************************
* 函数功能:设置背景图
* 参数类型:widget: 主窗口
           w, h:   图片的大小
           path:  图片路径
* 返回类型:无
********************************************************************/
void chang_background(GtkWidget *widget, int w, int h, const gchar *path);
 /*******************************************************************
* 函数功能:创建一张图片
* 参数类型:image_path:图片路径
           w, h:   图片的大小 
* 返回类型:图片控件
********************************************************************/
GtkWidget *image_new_from_file(const char *image_path, int w, int h);
/*******************************************************************
* 函数功能:给创建好的image重新设计一张图片
* 参数类型:image:    图片控件
           w, h:   图片的大小
           file_path:  图片路径
* 返回类型:无
********************************************************************/
void load_image(GtkWidget *image, const char *file_path, const int w, const int h );


#endif


   Makefile

SRC := #
SRC += main.c
SRC += gtk_function.c
SRC += gtk_window.c

#OBJ := $(subst .c,.o,$(SRC))
OBJ = $(SRC:%.c=%.o)

CC = gcc
FLAG = -Wall `pkg-config --cflags --libs gtk+-2.0`

EXEC_NAME = ../execute/demo
EXEC_PATH = .

.PHONY:clean call

call:$(OBJ)
	@echo make ...
	$(CC) $^ -o $(EXEC_PATH)/$(EXEC_NAME) $(FLAG) 
	@echo make over
	@echo Execute target is $(EXEC_PATH)/$(EXEC_NAME)
$(OBJ):%.o:%.c
	$(CC) -c -o $@ $< $(FLAG)
clean:
	@echo clean ...
	rm $(EXEC_PATH)/$(EXEC_NAME) *.o -rf
	@echo clean over
	

2、在image文件夹里放如下图片及对应名称:

                               

                         background.jpg                                                               main.png                           right.png                                    error.png 

3、在code目录下执行make命令,便在execute目录下生成demo的可执行程序。

4、运行程序后用鼠标滑动密码出现效果图如下:

            

       输入正确的密码  (密码正确终端会输出*****hello******)                                                    输入错误的密码

附:配置gtk编译环境

      1、安装
           sudo apt-get install libgtk2.0*     
           #gtk+2.0所需的所有文件统通下载安装完毕。
  
      2、测试
           运行:
                   pkg-config --cflags --libs gtk+-2.0
            现象:
                  -pthread -I/usr/local/include/gio-unix-2.0/ -I/usr/local/include/atk-1.0 -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/include/gtk-2.0

                  -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/freetype2 -I/usr/include/pixman-1 -I/usr/include/libpng12 
           说明成功

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值